Forum begins after the advertisement:
[Part 3] Player Do not take the recoil
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 3] Player Do not take the recoil
- This topic has 11 replies, 2 voices, and was last updated 4 months, 1 week ago by Joseph Tang.
-
AuthorPosts
-
August 18, 2024 at 3:11 pm #15606::
I’m on the part 3 of the series and i’m just done the recoil part. But when i test the recoil, only enemy getting pushing back but the player do not.
View post on imgur.com
here is my code, did i mess anything up? this is the recoil function<code> void Recoil() { if (playerStateList.recoilingX) { if (playerStateList.lookingRight) { rbd2.velocity = new Vector2(-recoilXSpeed, 0); } else { rbd2.velocity = new Vector2(recoilXSpeed, 0); } } if (playerStateList.recoilingY) { rbd2.gravityScale = 0; if (yAxis < 0) { rbd2.velocity = new Vector2(rbd2.velocity.x, recoilYSpeed); } else { rbd2.velocity = new Vector2(rbd2.velocity.x, -recoilYSpeed); } dbJumpCounter = 0; } else { rbd2.gravityScale = gravity; } //Stop recoil X if (playerStateList.recoilingX && stepXrecoiled < recoilXSteps) { stepXrecoiled++; } else { StopRecoilX(); } //Stop recoil Y if (playerStateList.recoilingY && stepYrecoiled < recoilYSteps) { stepYrecoiled++; } else { StopRecoilY(); } // if hit ground stop recoil Y if (isonGround()) { StopRecoilY(); } } void StopRecoilX() { stepXrecoiled = 0; playerStateList.recoilingX = false; } void StopRecoilY() { stepYrecoiled = 0; playerStateList.recoilingY = false; } void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilDir, float _recoilStrenght) { Collider2D[] objecttoHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer); if (objecttoHit.Length > 0) { _recoilDir = true; } for (int i = 0; i < objecttoHit.Length; i++) { if (objecttoHit[i].GetComponent<Enemy>() != null) { objecttoHit[i].GetComponent<Enemy>().EnemyHit(playerDmg, (transform.position - objecttoHit[i].transform.position).normalized, _recoilStrenght); } } } void Flip() { if (xAxis < 0) { transform.localScale = new Vector2(-1, transform.localScale.y); playerStateList.lookingRight = false; } else if (xAxis > 0) { transform.localScale = new Vector2(1, transform.localScale.y); playerStateList.lookingRight = true; } } </code>
August 19, 2024 at 4:28 pm #15614::Following our Article Part 3, step 5b) can you check whether your
Attack()
function has the following prerequisites:void Attack() { timeSinceAttack += Time.deltaTime; if(attack && timeSinceAttack >= timeBetweenAttack) { timeSinceAttack = 0; anim.SetTrigger("Attacking"); if(yAxis == 0 || yAxis < 0 && Grounded()) { Hit(SideAttackTransform, SideAttackArea , ref pState.recoilingX, recoilXSpeed); Instantiate(slashEffect, SideAttackTransform); } else if(yAxis > 0) { Hit(UpAttackTransform, UpAttackArea , ref pState.recoilingY, recoilYSpeed); SlashEffectAtAngle(slashEffect, 80, UpAttackTransform); } else if (yAxis < 0 && !Grounded()) { Hit(DownAttackTransform, DownAttackArea , ref pState.recoilingY, recoilYSpeed); SlashEffectAtAngle(slashEffect, -90, DownAttackTransform); } } }
Creating a Metroidvania (like Hollow Knight) — Part 3: Melee combat & Enemy AI Base Class
This code is used to activate recoil when the player has performed an attack.
August 19, 2024 at 4:40 pm #15616::<code> void Attack() { timeSinceattk += Time.deltaTime; if(attk && timeSinceattk >= timeBetweenattck) { timeSinceattk = 0; animator.SetTrigger("Attacking"); if (yAxis == 0 || yAxis < 0 && isonGround()) { Hit(sideAttackTransform, sideAttackArea, ref playerStateList.recoilingX, recoilXSpeed); } else if (yAxis > 0) { Hit(upAttackTransform, upAttackArea, ref playerStateList.recoilingY, recoilYSpeed); } else if (yAxis < 0 && !isonGround()) { Hit(downAttackTransform, downAttackArea, ref playerStateList.recoilingY, recoilYSpeed); } } }</code>
Yes i had it but i figure out that it is not having a recoil. It’s just for some reason if the enemy is too close or to far from enemy, the recoil won’t work. If the distance between player and enemy is at the right amount, the recoilling is work. Tks for your help!
August 19, 2024 at 4:48 pm #15618August 19, 2024 at 5:03 pm #15619::I don’t know why but after a day without any modification, the function work perfectly now when i tried to clip for you. Sorry for taking your time
August 19, 2024 at 5:05 pm #15620::That’s alright, sometimes we get reports of issues that are fixed through restarting Unity.
However, if you encounter any other issue again, feel free to ask.
August 19, 2024 at 5:39 pm #15621::View post on imgur.com
i want to ask that in this blood spurt we make in the controller. Should i assigned the blood spurt or the blood material?and why when i make this effect now my character only take dmg for once and doesn’t take dmg anymore. It not even triggered the hurt animationI assigned the bloodspurt and the hurt animation is work but i don’t see anything spash up when i taking dmgAugust 19, 2024 at 5:57 pm #15622August 19, 2024 at 5:59 pm #15623August 19, 2024 at 8:13 pm #15627::You can just send me all the code, copy and paste, otherwise find any piece of code related to taking damage.
August 19, 2024 at 8:42 pm #15630::This is the player controller
<code>using System; using System.Collections; using System.Collections.Generic; using Unity.Mathematics; using UnityEditor.Tilemaps; using UnityEngine; [RequireComponent (typeof(Rigidbody2D))] public class Move : MonoBehaviour { //animation and physic [Header("physic of player")] private Rigidbody2D rbd2; [SerializeField] public float speed = 2.0f; private float xAxis, yAxis; [SerializeField] private float jumpForce = 10; private int dbJumpCounter; [SerializeField] private int maxdbJump = 1; [Space(5)] [Header("Groundcheck setting")] [SerializeField] private Transform groundcheck; [SerializeField] private float groundchecky = 0.2f; [SerializeField] private float groundcheckx = 0.5f; [SerializeField] private LayerMask isground; Animator animator; [HideInInspector] public PlayerStateList playerStateList; [Space(5)] [Header("Coyotetime setting")] [SerializeField] private float coyoteTime = 0.1f; private float coyoteTimeCounter = 0; [Space(5)] [Header("Attacking setting")] [SerializeField] private float timeBetweenattck; [SerializeField] Transform sideAttackTransform, upAttackTransform, downAttackTransform; [SerializeField] Vector2 sideAttackArea, upAttackArea, downAttackArea; [SerializeField] LayerMask attackableLayer; [SerializeField] float playerDmg; private float timeSinceattk; bool attk = false; [Space(5)] [Header("Health Setting")] [SerializeField] public int health; [SerializeField] public int MaxHealth; [SerializeField] GameObject bloodSpurt; [SerializeField] float hitFlashspeed; public delegate void OnHealthChangedDelegate(); [HideInInspector] public OnHealthChangedDelegate onHealthChangedCallback; [Space(5)] [Header("Dash setting")] [SerializeField] private float dashSpeed; [SerializeField] private float dashTime; [SerializeField] private float dashCD; private bool canDash = true; private bool dashed; [Space(5)] [Header("Recoil")] [SerializeField] int recoilXSteps = 5; [SerializeField] int recoilYSteps = 5; [SerializeField] float recoilXSpeed = 100; [SerializeField] float recoilYSpeed = 100; int stepXrecoiled, stepYrecoiled; [Space(5)] bool restoreTime; float restoreTimeSpeed; private SpriteRenderer spriteRenderer; public static Move Instance; private float gravity; private void Awake() { if( Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } Health = MaxHealth; } // Start is called before the first frame update private void Start() { //player game object playerStateList = GetComponent<PlayerStateList>(); rbd2 = GetComponent<Rigidbody2D>(); animator = GetComponent<Animator>(); spriteRenderer = GetComponent<SpriteRenderer>(); gravity = rbd2.gravityScale; } private void OnDrawGizmos() { Gizmos.color = Color.yellow; Gizmos.DrawWireCube(sideAttackTransform.position, sideAttackArea); Gizmos.DrawWireCube(upAttackTransform.position, upAttackArea); Gizmos.DrawWireCube(downAttackTransform.position, downAttackArea); } // Update is called once per frame private void Update() { getInput(); UpdateJump(); if (playerStateList.dashing) return; Flip(); Moving(); Jump(); StartDash(); Attack(); RestoreTimeScale(); FlashWhenInvi(); } private void FixedUpdate() { if(playerStateList.dashing) return; Recoil(); } void getInput() { xAxis = Input.GetAxisRaw("Horizontal"); yAxis = Input.GetAxisRaw("Vertical"); attk = Input.GetButtonDown("Attack"); } //player Attack void Attack() { timeSinceattk += Time.deltaTime; if(attk && timeSinceattk >= timeBetweenattck) { timeSinceattk = 0; animator.SetTrigger("Attacking"); if (yAxis == 0 || yAxis < 0 && isonGround()) { Hit(sideAttackTransform, sideAttackArea, ref playerStateList.recoilingX, recoilXSpeed); } else if (yAxis > 0) { Hit(upAttackTransform, upAttackArea, ref playerStateList.recoilingY, recoilYSpeed); } else if (yAxis < 0 && !isonGround()) { Hit(downAttackTransform, downAttackArea, ref playerStateList.recoilingY, recoilYSpeed); } } } //Using for the character recoil void Recoil() { if (playerStateList.recoilingX) { if (playerStateList.lookingRight) { rbd2.velocity = new Vector2(-recoilXSpeed, 0); } else { rbd2.velocity = new Vector2(recoilXSpeed, 0); } } if (playerStateList.recoilingY) { rbd2.gravityScale = 0; if (yAxis < 0) { rbd2.velocity = new Vector2(rbd2.velocity.x, recoilYSpeed); } else { rbd2.velocity = new Vector2(rbd2.velocity.x, -recoilYSpeed); } dbJumpCounter = 0; } else { rbd2.gravityScale = gravity; } //Stop recoil X if (playerStateList.recoilingX && stepXrecoiled < recoilXSteps) { stepXrecoiled++; } else { StopRecoilX(); } //Stop recoil Y if (playerStateList.recoilingY && stepYrecoiled < recoilYSteps) { stepYrecoiled++; } else { StopRecoilY(); } // if hit ground stop recoil Y if (isonGround()) { StopRecoilY(); } } void StopRecoilX() { stepXrecoiled = 0; playerStateList.recoilingX = false; } void StopRecoilY() { stepYrecoiled = 0; playerStateList.recoilingY = false; } //player hit check void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilDir, float _recoilStrenght) { Collider2D[] objecttoHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer); List<Enemy> hitonEnemies = new List<Enemy>(); if (objecttoHit.Length > 0) { _recoilDir = true; } for (int i = 0; i < objecttoHit.Length; i++) { Enemy e = objecttoHit[i].GetComponent<Enemy>(); if (e && !hitonEnemies.Contains(e)) { e.EnemyHit(playerDmg, (transform.position - objecttoHit[i].transform.position).normalized, _recoilStrenght); hitonEnemies.Add(e); } } } //change dir of the player void Flip() { if (xAxis < 0) { transform.localScale = new Vector2(-1, transform.localScale.y); playerStateList.lookingRight = false; } else if (xAxis > 0) { transform.localScale = new Vector2(1, transform.localScale.y); playerStateList.lookingRight = true; } } // start the dash void StartDash() { if (Input.GetButtonDown("Dash") && canDash && !dashed) { StartCoroutine(Dash()); dashed = true; } if (isonGround()) { dashed = false; } } IEnumerator Dash() { canDash = false; playerStateList.dashing = true; animator.SetTrigger("Dashing"); rbd2.gravityScale = 0; rbd2.velocity = new Vector2(transform.localScale.x * dashSpeed, 0); yield return new WaitForSeconds(dashTime); rbd2.gravityScale = gravity; playerStateList.dashing = false; yield return new WaitForSeconds(dashCD); canDash = true; } //moving of player private void Moving() { rbd2.velocity = new Vector2 (speed * xAxis, rbd2.velocity.y ); animator.SetBool("Walking", rbd2.velocity.x != 0 && isonGround()); } //check if player is on the ground or not public bool isonGround() { if (Physics2D.Raycast(groundcheck.position, Vector2.down, groundchecky, isground) || Physics2D.Raycast(groundcheck.position + new Vector3(groundcheckx, 0, 0), Vector2.down, groundchecky, isground) || Physics2D.Raycast(groundcheck.position + new Vector3(-groundcheckx, 0, 0), Vector2.down, groundchecky, isground) ) { return true; } else { return false; } } //player jump void Jump() { if (Input.GetButtonDown("Jump") && coyoteTimeCounter > 0) { rbd2.velocity = new Vector3(rbd2.velocity.x, jumpForce); /* playerStateList.Jumping = true;*/ } else if (!isonGround() && dbJumpCounter < maxdbJump && Input.GetButtonDown("Jump")) { dbJumpCounter++; rbd2.velocity = new Vector3(rbd2.velocity.x, jumpForce); } animator.SetBool("Jumping", !isonGround()); } void UpdateJump() { if(isonGround()) { /* playerStateList.Jumping = false;*/ coyoteTimeCounter = coyoteTime; dbJumpCounter = 0; } else { coyoteTimeCounter -= Time.deltaTime; } } //stop taking dmg when player get hit IEnumerator StopTakingDmg() { playerStateList.Invi = true; GameObject _bloodSpurtParticles = Instantiate(bloodSpurt, transform.position, Quaternion.identity); Destroy(_bloodSpurtParticles, 1f); animator.SetTrigger("TakeDmg"); yield return new WaitForSeconds(1f); playerStateList.Invi = false; } //player health calculated public int Health { get { return health; } set { if (health != value) { health = Mathf.Clamp(value, 0, MaxHealth); if(onHealthChangedCallback != null) { onHealthChangedCallback.Invoke(); } } } } //take dmg function public void takeDmg(float _Dmg) { Health -= Mathf.RoundToInt(_Dmg); StartCoroutine(StopTakingDmg()); } //time delay for player when get hit public void HitStopTime(float _newTimeScale, int _restoreSpeed, float _delay) { restoreTimeSpeed = _restoreSpeed; Time.timeScale = _newTimeScale; if (_delay > 0) { StopCoroutine(TimeStartAgain(_delay)); StartCoroutine(TimeStartAgain(_delay)); } else { restoreTime = true; } } void RestoreTimeScale() { if (restoreTime) { if (Time.timeScale < 1) { Time.timeScale += Time.unscaledDeltaTime * restoreTimeSpeed; } else { Time.timeScale = 1; restoreTime = false; } } } IEnumerator TimeStartAgain(float _delay) { yield return new WaitForSecondsRealtime(_delay); restoreTime = true; } void FlashWhenInvi() { spriteRenderer.material.color = playerStateList.Invi ? Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time * hitFlashspeed, 0.5f)) : Color.white; } } </code>
And this is the enemy controller
<code>using System; using System.Collections; using System.Collections.Generic; using Unity.Mathematics; using UnityEditor.Tilemaps; using UnityEngine; [RequireComponent (typeof(Rigidbody2D))] public class Move : MonoBehaviour { //animation and physic [Header("physic of player")] private Rigidbody2D rbd2; [SerializeField] public float speed = 2.0f; private float xAxis, yAxis; [SerializeField] private float jumpForce = 10; private int dbJumpCounter; [SerializeField] private int maxdbJump = 1; [Space(5)] [Header("Groundcheck setting")] [SerializeField] private Transform groundcheck; [SerializeField] private float groundchecky = 0.2f; [SerializeField] private float groundcheckx = 0.5f; [SerializeField] private LayerMask isground; Animator animator; [HideInInspector] public PlayerStateList playerStateList; [Space(5)] [Header("Coyotetime setting")] [SerializeField] private float coyoteTime = 0.1f; private float coyoteTimeCounter = 0; [Space(5)] [Header("Attacking setting")] [SerializeField] private float timeBetweenattck; [SerializeField] Transform sideAttackTransform, upAttackTransform, downAttackTransform; [SerializeField] Vector2 sideAttackArea, upAttackArea, downAttackArea; [SerializeField] LayerMask attackableLayer; [SerializeField] float playerDmg; private float timeSinceattk; bool attk = false; [Space(5)] [Header("Health Setting")] [SerializeField] public int health; [SerializeField] public int MaxHealth; [SerializeField] GameObject bloodSpurt; [SerializeField] float hitFlashspeed; public delegate void OnHealthChangedDelegate(); [HideInInspector] public OnHealthChangedDelegate onHealthChangedCallback; [Space(5)] [Header("Dash setting")] [SerializeField] private float dashSpeed; [SerializeField] private float dashTime; [SerializeField] private float dashCD; private bool canDash = true; private bool dashed; [Space(5)] [Header("Recoil")] [SerializeField] int recoilXSteps = 5; [SerializeField] int recoilYSteps = 5; [SerializeField] float recoilXSpeed = 100; [SerializeField] float recoilYSpeed = 100; int stepXrecoiled, stepYrecoiled; [Space(5)] bool restoreTime; float restoreTimeSpeed; private SpriteRenderer spriteRenderer; public static Move Instance; private float gravity; private void Awake() { if( Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } Health = MaxHealth; } // Start is called before the first frame update private void Start() { //player game object playerStateList = GetComponent<PlayerStateList>(); rbd2 = GetComponent<Rigidbody2D>(); animator = GetComponent<Animator>(); spriteRenderer = GetComponent<SpriteRenderer>(); gravity = rbd2.gravityScale; } private void OnDrawGizmos() { Gizmos.color = Color.yellow; Gizmos.DrawWireCube(sideAttackTransform.position, sideAttackArea); Gizmos.DrawWireCube(upAttackTransform.position, upAttackArea); Gizmos.DrawWireCube(downAttackTransform.position, downAttackArea); } // Update is called once per frame private void Update() { getInput(); UpdateJump(); if (playerStateList.dashing) return; Flip(); Moving(); Jump(); StartDash(); Attack(); RestoreTimeScale(); FlashWhenInvi(); } private void FixedUpdate() { if(playerStateList.dashing) return; Recoil(); } void getInput() { xAxis = Input.GetAxisRaw("Horizontal"); yAxis = Input.GetAxisRaw("Vertical"); attk = Input.GetButtonDown("Attack"); } //player Attack void Attack() { timeSinceattk += Time.deltaTime; if(attk && timeSinceattk >= timeBetweenattck) { timeSinceattk = 0; animator.SetTrigger("Attacking"); if (yAxis == 0 || yAxis < 0 && isonGround()) { Hit(sideAttackTransform, sideAttackArea, ref playerStateList.recoilingX, recoilXSpeed); } else if (yAxis > 0) { Hit(upAttackTransform, upAttackArea, ref playerStateList.recoilingY, recoilYSpeed); } else if (yAxis < 0 && !isonGround()) { Hit(downAttackTransform, downAttackArea, ref playerStateList.recoilingY, recoilYSpeed); } } } //Using for the character recoil void Recoil() { if (playerStateList.recoilingX) { if (playerStateList.lookingRight) { rbd2.velocity = new Vector2(-recoilXSpeed, 0); } else { rbd2.velocity = new Vector2(recoilXSpeed, 0); } } if (playerStateList.recoilingY) { rbd2.gravityScale = 0; if (yAxis < 0) { rbd2.velocity = new Vector2(rbd2.velocity.x, recoilYSpeed); } else { rbd2.velocity = new Vector2(rbd2.velocity.x, -recoilYSpeed); } dbJumpCounter = 0; } else { rbd2.gravityScale = gravity; } //Stop recoil X if (playerStateList.recoilingX && stepXrecoiled < recoilXSteps) { stepXrecoiled++; } else { StopRecoilX(); } //Stop recoil Y if (playerStateList.recoilingY && stepYrecoiled < recoilYSteps) { stepYrecoiled++; } else { StopRecoilY(); } // if hit ground stop recoil Y if (isonGround()) { StopRecoilY(); } } void StopRecoilX() { stepXrecoiled = 0; playerStateList.recoilingX = false; } void StopRecoilY() { stepYrecoiled = 0; playerStateList.recoilingY = false; } //player hit check void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilDir, float _recoilStrenght) { Collider2D[] objecttoHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer); List<Enemy> hitonEnemies = new List<Enemy>(); if (objecttoHit.Length > 0) { _recoilDir = true; } for (int i = 0; i < objecttoHit.Length; i++) { Enemy e = objecttoHit[i].GetComponent<Enemy>(); if (e && !hitonEnemies.Contains(e)) { e.EnemyHit(playerDmg, (transform.position - objecttoHit[i].transform.position).normalized, _recoilStrenght); hitonEnemies.Add(e); } } } //change dir of the player void Flip() { if (xAxis < 0) { transform.localScale = new Vector2(-1, transform.localScale.y); playerStateList.lookingRight = false; } else if (xAxis > 0) { transform.localScale = new Vector2(1, transform.localScale.y); playerStateList.lookingRight = true; } } // start the dash void StartDash() { if (Input.GetButtonDown("Dash") && canDash && !dashed) { StartCoroutine(Dash()); dashed = true; } if (isonGround()) { dashed = false; } } IEnumerator Dash() { canDash = false; playerStateList.dashing = true; animator.SetTrigger("Dashing"); rbd2.gravityScale = 0; rbd2.velocity = new Vector2(transform.localScale.x * dashSpeed, 0); yield return new WaitForSeconds(dashTime); rbd2.gravityScale = gravity; playerStateList.dashing = false; yield return new WaitForSeconds(dashCD); canDash = true; } //moving of player private void Moving() { rbd2.velocity = new Vector2 (speed * xAxis, rbd2.velocity.y ); animator.SetBool("Walking", rbd2.velocity.x != 0 && isonGround()); } //check if player is on the ground or not public bool isonGround() { if (Physics2D.Raycast(groundcheck.position, Vector2.down, groundchecky, isground) || Physics2D.Raycast(groundcheck.position + new Vector3(groundcheckx, 0, 0), Vector2.down, groundchecky, isground) || Physics2D.Raycast(groundcheck.position + new Vector3(-groundcheckx, 0, 0), Vector2.down, groundchecky, isground) ) { return true; } else { return false; } } //player jump void Jump() { if (Input.GetButtonDown("Jump") && coyoteTimeCounter > 0) { rbd2.velocity = new Vector3(rbd2.velocity.x, jumpForce); /* playerStateList.Jumping = true;*/ } else if (!isonGround() && dbJumpCounter < maxdbJump && Input.GetButtonDown("Jump")) { dbJumpCounter++; rbd2.velocity = new Vector3(rbd2.velocity.x, jumpForce); } animator.SetBool("Jumping", !isonGround()); } void UpdateJump() { if(isonGround()) { /* playerStateList.Jumping = false;*/ coyoteTimeCounter = coyoteTime; dbJumpCounter = 0; } else { coyoteTimeCounter -= Time.deltaTime; } } //stop taking dmg when player get hit IEnumerator StopTakingDmg() { playerStateList.Invi = true; GameObject _bloodSpurtParticles = Instantiate(bloodSpurt, transform.position, Quaternion.identity); Destroy(_bloodSpurtParticles, 1f); animator.SetTrigger("TakeDmg"); yield return new WaitForSeconds(1f); playerStateList.Invi = false; } //player health calculated public int Health { get { return health; } set { if (health != value) { health = Mathf.Clamp(value, 0, MaxHealth); if(onHealthChangedCallback != null) { onHealthChangedCallback.Invoke(); } } } } //take dmg function public void takeDmg(float _Dmg) { Health -= Mathf.RoundToInt(_Dmg); StartCoroutine(StopTakingDmg()); } //time delay for player when get hit public void HitStopTime(float _newTimeScale, int _restoreSpeed, float _delay) { restoreTimeSpeed = _restoreSpeed; Time.timeScale = _newTimeScale; if (_delay > 0) { StopCoroutine(TimeStartAgain(_delay)); StartCoroutine(TimeStartAgain(_delay)); } else { restoreTime = true; } } void RestoreTimeScale() { if (restoreTime) { if (Time.timeScale < 1) { Time.timeScale += Time.unscaledDeltaTime * restoreTimeSpeed; } else { Time.timeScale = 1; restoreTime = false; } } } IEnumerator TimeStartAgain(float _delay) { yield return new WaitForSecondsRealtime(_delay); restoreTime = true; } void FlashWhenInvi() { spriteRenderer.material.color = playerStateList.Invi ? Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time * hitFlashspeed, 0.5f)) : Color.white; } } </code>
August 19, 2024 at 8:54 pm #15634::Just to be sure, your player shows the hurt animation right? If yes, then the prefab should be spawning in the scene.
Can you check in your Hierarchy that when you get hit, a bloodspurt prefab is created in the scene? You’ll know since the gameobject will appear in the bottom of the hierarchy.
Next, can you try zooming out the camera from your player to see if the reason you cant see the prefab is because the splash is out of frame? [The particles are too fast and move away from your view faster than expected]?
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: