Forum begins after the advertisement:
[part 10] dive causes unity to freeze completely
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [part 10] dive causes unity to freeze completely
- This topic has 45 replies, 3 voices, and was last updated 10 months, 2 weeks ago by
Niyam Shah.
-
AuthorPosts
-
October 7, 2024 at 10:46 pm #15991::
also for my camera, it was set up properly as this jitteryness only occured when i switched laptops. Strange errors just appeared when switching laptops such as :
camera jitters and bat enemy moved very slowly(fixed now)
ichecked and im using the same unity editor version
October 8, 2024 at 3:18 pm #15996::I am not certain about why your camera is not smoothly tracking your player, but focusing on the boss for now, can you test out the boss again.
First, let’s Change your Dive animation to stop looping. You can do so by going into the Boss Animator/Animation and finding the Dive animation clip, double clicking it for the Inspector and turning off Loop.
Then let’s test whether the Dive will stop should the boss touch the ground.
Normally, the boss would move above the player, I think something might be wrong with the BossIdle script so let’s just try something by stopping it entirely whenever the boss wants to dive.
public class WoodenBotIdle : StateMachineBehaviour { Rigidbody2D rb; // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { rb = animator.GetComponentInParent<Rigidbody2D>(); } // OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { if(!WoodenBot.Instance.diveAttack) { rb.velocity = Vector2.zero; RunToPlayer(animator); if(WoodenBot.Instance.attackCountdown <= 0) { WoodenBot.Instance.AttackHandler(); WoodenBot.Instance.attackCountdown = Random.Range(WoodenBot.Instance.attackTimer - 1, WoodenBot.Instance.attackTimer + 1); } if (!WoodenBot.Instance.Grounded()) { rb.velocity = new Vector2(rb.velocity.x, -25); } } } void RunToPlayer(Animator animator) { if(Vector2.Distance(PlayerController.Instance.transform.position, rb.position) > WoodenBot.Instance.attackRange) { animator.SetBool("Run", true); } else { return; } } // OnStateExit is called when a transition ends and the state machine finishes evaluating this state override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { } }
This way we can see if the Idle script is impacting the Dive in any way.
Finally, the Parry is supposed to turn off the diveAttack boolean through the method ResetAllAttacks, but that doesn’t stop the animator bools if I remember correctly. Thus, Let’s focus on trying to get the Boss to complete the Dive Attack before anything.
Try these few things:
- While the boss is stuck in the Dive Animation, Move the boss in the inspector upwards by a bit. If the boss continues movement on it’s own, then it may just be stuck on the floor’s collision for some reason.
Otherwise, 2) Move the boss back onto the ground after raising them in the air. If the boss completes the dive attack, then the Dive Attack is working fine but the boss simply cannot move.
If the boss does not finish the dive upon touching the ground 3) Move the boss into the air and make it touch a wall. We implemented a wall check method for Dive and other attacks to immediately fall to the ground should they hit a wall. So this should work in letting the boss complete the attack while stuck. Just make sure the wall check is facing the correct direction when you move the boss to touch the wall. (Move the boss to touch the right wall if the wall check is on the right side of the boss.
October 8, 2024 at 10:39 pm #16005::i just attemped all methods with no new results?
i also want to say that sometimes the barrage attack will get stuck in the bendown animation – however, the boss will cotinue as normal if i hit the boss and it finishes parrying?
really not sure whats wrong
October 9, 2024 at 1:41 pm #16010::I think going simple, Is the looping animation your Jump animation?
If it’s your jump animation can you check what your Jump state script has? and if there could be anything interfering with it calling
Dive()
in your boss script due to the player’s distance? In any case, could you send the jump script.October 9, 2024 at 2:30 pm #16011::heres the jump scripy:
<code>using System.Collections; using System.Collections.Generic; using UnityEngine; public class WoodenBotJump : StateMachineBehaviour { Rigidbody2D rb; // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { rb = animator.GetComponentInParent<Rigidbody2D>(); } override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { DiveAttack(); } void DiveAttack() { if (WoodenBot.Instance.diveAttack) { WoodenBot.Instance.Flip(); Vector2 _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * 3 * Time.fixedDeltaTime); rb.MovePosition(_newPos); float _distance = Vector2.Distance(rb.position, _newPos); if (_distance < 0.1f) { WoodenBot.Instance.Dive(); } if (WoodenBot.Instance.TouchedWall()) { WoodenBot.Instance.moveToPosition.x = rb.velocity.x; _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * Random.Range(2, 4) * Time.fixedDeltaTime); } } } override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { } }</code>
October 9, 2024 at 3:25 pm #16012::Let’s try something first for the dive and tell me the result:
public class WoodenBotJump : StateMachineBehaviour { Rigidbody2D rb; // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { rb = animator.GetComponentInParent<Rigidbody2D>(); } override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { DiveAttack(); } void DiveAttack() { if (WoodenBot.Instance.diveAttack) { WoodenBot.Instance.Flip(); Vector2 _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * 3 * Time.fixedDeltaTime); rb.MovePosition(_newPos); float _distance = Vector2.Distance(rb.position, _newPos); if (_distance < 0.1f) { WoodenBot.Instance.Dive(); } if (WoodenBot.Instance.TouchedWall()) { WoodenBot.Instance.moveToPosition.x = rb.velocity.x; _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * Random.Range(2, 4) * Time.fixedDeltaTime); } } else { animator.SetBool("Jump", false); } } override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { } }
What we’re doing here is checking if the Boss’ diveattack bool is turned off, causing the boss to be stuck in it’s jump state since it cannot call anything to get out of it. We could have also checked this on the Debug menu for the inspector, but through this way we can see it happen visually.
If your boss is unable to dive attack anymore/jump while you are close that means that for some reason the diveattack is turned off.
Also, can I just check with you that whenever you test the bug where the boss loops it’s dive, you only went close to it, did not attack it whatsoever?
October 9, 2024 at 9:00 pm #16014::Ok some progress was made The boss sometimes does the jumping animation and it will freeze on the last frame on the ground instead of looping
However I’ve noticed tje error happens significantly less but still does occur
October 11, 2024 at 12:38 am #16022::Let’s set up some prints in
ResetAllAttacks()
andDiveAttackJump()
to see when they are being called.One of the only reasons why your boss is unable to come out of the dive is because the jump animation for some reason is not able to progress it’s
OnStateUpdate()
function. So likely thediveAttack
bool is being set to false somehow, which is why we did the previous step of adding an else statement to exit the jump state.Now, the only way to set the
diveAttack
to false is throughResetAllAttacks()
and completing the dive itself.public void ResetAllAttacks() { attacking = false; StopCoroutine(Lunge()); StopCoroutine(Parry()); StopCoroutine(TripleSlash()); StopCoroutine(Slash()); diveAttack = false; print("DiveAttack off"); barrageAttack = false; outbreakAttack = false; bounceAttack = false; } void DiveAttackJump() { attacking = true; moveToPosition = new Vector2(PlayerController.Instance.transform.position.x, rb.position.y + 10); diveAttack = true; anim.SetBool("Jump", true); print("Starting Jump"); }
Let’s also check that your the else statement jump is also activating.
public class WoodenBotJump : StateMachineBehaviour { Rigidbody2D rb; // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { rb = animator.GetComponentInParent(); } override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { DiveAttack(); } void DiveAttack() { if (WoodenBot.Instance.diveAttack) { WoodenBot.Instance.Flip(); Vector2 _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * 3 * Time.fixedDeltaTime); rb.MovePosition(_newPos); float _distance = Vector2.Distance(rb.position, _newPos); if (_distance < 0.1f) { WoodenBot.Instance.Dive(); } if (WoodenBot.Instance.TouchedWall()) { WoodenBot.Instance.moveToPosition.x = rb.velocity.x; _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * Random.Range(2, 4) * Time.fixedDeltaTime); } } else { print("Stopping Jump"); animator.SetBool("Jump", false); } } override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { } }
Now could you record another video showing the console and triggering the error a couple times?
October 11, 2024 at 5:33 am #16026::the boss not working is infrequent but it does now revert to normal when hit.Also ive had to altersome of the code for the WoodenBotJump script since it wasnt working and piling with errors: it should be the same as urs justin a different order?
<code>public class WoodenBotJump : StateMachineBehaviour { Rigidbody2D rb; // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { rb = animator.GetComponentInParent<Rigidbody2D>(); } override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { if (WoodenBot.Instance.diveAttack) { DiveAttack(); } else { animator.SetBool("Jump", false); Debug.Log("JumpAttack Off"); WoodenBot.Instance.ResetAllAttacks(); } } void DiveAttack() { if (WoodenBot.Instance.diveAttack) { WoodenBot.Instance.Flip(); Vector2 _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * 3 * Time.fixedDeltaTime); rb.MovePosition(_newPos); float _distance = Vector2.Distance(rb.position, _newPos); if (_distance < 0.1f) { WoodenBot.Instance.Dive(); } if (WoodenBot.Instance.TouchedWall()) { WoodenBot.Instance.moveToPosition.x = rb.velocity.x; _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * Random.Range(2, 4) * Time.fixedDeltaTime); } } } override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { } }</code>
October 12, 2024 at 1:31 pm #16042::Sorry, but the print codes only work if we are able to see the console window whenever you test the boss out.
Could you deactivate “Play Focused” to something else and keep your Console window open in your unity so we can see when the print messages are being made.
Next this might be the problem as to why your dive stops working, the
ResetAllAttacks()
is delayed by so long after the boss performs a slash that it stops the diveattack when it happens occasionally. Perhaps why it happens so infrequently at all. This might also solve your Barrage attack issue similarly.IEnumerator Slash() { attacking = true; rb.velocity = Vector2.zero; anim.SetTrigger("Slash"); SlashAngle(); yield return new WaitForSeconds(
20.2); ResetAllAttacks(); }October 12, 2024 at 7:04 pm #16044::ok i changed the code above and noticed attacks are quicker but the error does occur sometimes (less than usual)?
also a new error occured (goddamit) – in my game i have walls so i can wall jump over the boss, if i wall jump as the boss is trying to jump to my position, it will position in the y position correctly but will begin to fly to the right wall until it hits the wall
The dive is being chosen in the attack handler and jump is started but it just freezes?
View post on imgur.com
October 13, 2024 at 8:01 pm #16053::Sorry, the print codes are pretty inefficient but I would like to see you start the boss fight and attack the boss leading up to the Dive error rather than the aftermath as its a bit hard to conclude what could have happened.
I want you to go to your Boss script and comment out all other attacks from the attackhandler method. Place Dive as the attack for the Boss in Stage 1. And Do Not Hit the Boss.
We will test this to see if you are able to replicate the bug without hitting the boss. You can change the Boss’ Damage to 1 to make sure you don’t die either.
Again, I would believe that it’s due to
ResetAllAttacks()
being called, but it’s hard to determine. So if you are not able to replicate the bug while doing this, then it’s most probably due toResetAllAttacks()
turning off the dive.
Aside from that, your bug of jumping to the other wall, Do you mean it goes to the opposite end of the player? If you can record that too, that would help. [You can do the same instruction above and replace your attacks with whichever move it was that caused the wall bug].
My only guess right now would be that it was the bounce attack getting your player’s position from behind them and that their position targeting is not rooted to the ground but just the player’s current position.
October 13, 2024 at 8:56 pm #16054::View post on imgur.com
ok so the error doesnt occur when not attacking the boss
i also have footage of the boss getting stuck on the wall (happens really rarely so footage of it was hard to find) – i implemented a bakwall checker aswell but this has no effect on the boss(it did fix an error with the boss getting stuck before so the backwallchecker should work)
October 15, 2024 at 1:11 pm #16078::It took me a while but i just came to a realization, could you try removing all the prints and the if statement of diveattack in you jump script, like this?
public class WoodenBotJump : StateMachineBehaviour { Rigidbody2D rb; // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { rb = animator.GetComponentInParent<Rigidbody2D>(); } override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { if (WoodenBot.Instance.diveAttack) { DiveAttack(); }
else { animator.SetBool("Jump", false); Debug.Log("JumpAttack Off"); WoodenBot.Instance.ResetAllAttacks(); }} void DiveAttack() {if (WoodenBot.Instance.diveAttack) {WoodenBot.Instance.Flip(); Vector2 _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * 3 * Time.fixedDeltaTime); rb.MovePosition(_newPos); float _distance = Vector2.Distance(rb.position, _newPos); if (_distance < 0.1f) { WoodenBot.Instance.Dive(); } if (WoodenBot.Instance.TouchedWall()) { WoodenBot.Instance.moveToPosition.x = rb.velocity.x; _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * Random.Range(2, 4) * Time.fixedDeltaTime); }}} override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { } }
This should guarantee that your dive will work whenever you jump, but it will also not stop after committing a jump animation.
October 15, 2024 at 3:29 pm #16080October 15, 2024 at 3:33 pm #16081October 15, 2024 at 11:37 pm #16085::both errors unfortunately…..
ive tried fiddling with the code and stopping the jumping animation when walled but nothing seems to work??
October 16, 2024 at 12:14 am #16087::Let’s try to figure out more details on this.
Could you send another video where you move the boss around using the inspector while the bug has occured.
Currently, the Boss is not continuously restarting the Jump Animation correct? Is the Boss able to get into the air while attempting to Dive? Can You move the boss around while it’s in the air and see if it goes back to the same spot? (Control the Boss’ transform Y/X values and play with it to see if it’s MoveTo is actually working) And does the boss activate the dive attack if you control it to hit the ground?
October 16, 2024 at 2:39 am #16091::i got videos of the wall stuck error. the normal not moving error is really hard to replicate and get on camera.
when on the wall, the boss continuously repeats the jump animation
View post on imgur.com
i realised that the reset all atttacks function is the problem since i was fiddling with the woodenbot code:#
this causes the bot to cease the jump animation when hitting a wall but will cause the bot to stay idle(since resetallattacks hasnt been called):
protected override void Update() { base.Update(); if (TouchedWall()) { anim.SetBool("Jump", false); } }
however, changing it to this causes the error to persist:
<code> protected override void Update() { base.Update(); if (TouchedWall()) { ResetAllAttacks(); anim.SetBool("Jump", false); } }</code>
clearly somehow the resetallattacks function causes this error??? (ive tried putting “anim.SetBool(“jumping”, false)” into resetallattacks but nothing changes)
ill send the entire woodenbot code (just the important bits)
<code>using System.Collections; using System.Collections.Generic; using UnityEngine; public class WoodenBot : Enemy { public static WoodenBot Instance; [Header("Ground Check Settings")] [SerializeField] private Transform groundCheckPoint; [SerializeField] private float groundCheckY = 0.2f; [SerializeField] private float groundCheckX = 0.5f; [SerializeField] private LayerMask whatIsGround; [SerializeField] private Transform wallCheckPoint; [SerializeField] private Transform backWallCheckPoint; int hitCounter; bool stunned, canStun; bool alive; [HideInInspector] public bool facingRight; [HideInInspector] public float runSpeed; [HideInInspector] public bool damagePlayer = false; [HideInInspector] public bool parrying; [HideInInspector] public Vector2 moveToPosition; [Space(5)] [Header("attack settings")] [SerializeField] public Transform SideAttackTransform, UpAttackTransform, DownAttackTransform; [SerializeField] public Vector2 SideAttackArea, UpAttackArea, DownAttackArea; [SerializeField] public GameObject slashEffect; [SerializeField] public GameObject lungeBomb; public float attackRange; public float attackTimer; [HideInInspector] public bool diveAttack; public GameObject divingCollider; public GameObject pillar; [HideInInspector] public bool barrageAttack; public GameObject barrageFireball; [HideInInspector] public bool outbreakAttack; [HideInInspector] public bool bounceAttack; [HideInInspector] public float rotationDirectionToTarget; [HideInInspector] public int bounceCount; SpriteRenderer sprite; public bool Grounded() { if (Physics2D.Raycast(groundCheckPoint.position, Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(groundCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(groundCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround)) { return true; } else { return false; } } public bool TouchedWall() { if (Physics2D.Raycast(wallCheckPoint.position, Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(wallCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(wallCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(backWallCheckPoint.position, Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(backWallCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) || Physics2D.Raycast(backWallCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround)) { return true; } else { return false; } } private void OnDrawGizmos() { Gizmos.color = Color.red; Gizmos.DrawWireCube(SideAttackTransform.position, SideAttackArea); Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea); Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea); } private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } } // Start is called before the first frame update protected override void Start() { base.Start(); sprite = GetComponentInChildren<SpriteRenderer>(); anim = GetComponentInChildren<Animator>(); ChangeState(EnemyStates.woodenBot_stage1); alive = true; } // Update is called once per frame protected override void Update() { base.Update(); if (TouchedWall()) { ResetAllAttacks(); anim.SetBool("Jump", false); } if (health <= 0 && alive) { Death(0); } if (!attacking) { attackCountdown -= Time.deltaTime; } if (stunned) { rb.velocity = Vector2.zero; } } public void Flip() { if (PlayerController.Instance.transform.position.x < transform.position.x && transform.localScale.x > 0) { transform.eulerAngles = new Vector2(transform.eulerAngles.x, 180); facingRight = false; } else { transform.eulerAngles = new Vector2(transform.eulerAngles.x, 0); facingRight = true; } } protected override void UpdateEnemyStates() { if (PlayerController.Instance != null) { switch (GetCurrentEnemyState) { case EnemyStates.woodenBot_stage1: attackTimer = 4; canStun = true; runSpeed = speed; break; case EnemyStates.woodenBot_stage2: canStun = true; attackTimer = 3; break; case EnemyStates.woodenBot_stage3: canStun = false; attackTimer = 2; break; case EnemyStates.woodenBot_stage4: canStun= false; attackTimer = 2; break; } } } protected override void OnCollisionStay2D(Collision2D _other) { } #region attacking #region variables [HideInInspector] public bool attacking; [HideInInspector] public float attackCountdown; #endregion #endregion #region AttackHandler public void AttackHandler() { if (currentEnemyState == EnemyStates.woodenBot_stage1) { Debug.Log("Stage 1"); if (Vector2.Distance(PlayerController.Instance.transform.position, rb.position) <= attackRange) { DiveAttackJump(); } else { DiveAttackJump(); } } if (currentEnemyState == EnemyStates.woodenBot_stage2) { Debug.Log("Stage 2"); if (Vector2.Distance(PlayerController.Instance.transform.position, rb.position) <= attackRange) { DiveAttackJump(); } else { int _attackChosen = Random.Range(1, 3); if (_attackChosen == 1) { DiveAttackJump(); Debug.Log("dive chosen"); } if (_attackChosen == 2) { DiveAttackJump(); Debug.Log("lunge chosen"); } } } if (currentEnemyState == EnemyStates.woodenBot_stage3) { Debug.Log("Stage 3"); if (Vector2.Distance(PlayerController.Instance.transform.position, rb.position) <= attackRange) { StartCoroutine(TripleSlash()); } else { int _attackChosen = Random.Range(1, 5); if (_attackChosen == 1) { OutBreakBendDown(); } if (_attackChosen == 2) { DiveAttackJump(); } if (_attackChosen == 3) { BarrageBendDown(); } if (_attackChosen == 4) { BounceAttack(); } } } if (currentEnemyState == EnemyStates.woodenBot_stage4) { Debug.Log("Stage 4"); if (Vector2.Distance(PlayerController.Instance.transform.position, rb.position) <= attackRange) { StartCoroutine(Slash()); } else { int _attackChosen = Random.Range(1, 4); if (_attackChosen == 1) { OutBreakBendDown(); } if (_attackChosen == 2) { DiveAttackJump(); } if (_attackChosen == 3) { BounceAttack(); } } } } public void ResetAllAttacks() { attacking = false; StopCoroutine(Lunge()); StopCoroutine(Parry()); StopCoroutine(TripleSlash()); StopCoroutine(Slash()); diveAttack = false; print("DiveAttack off"); barrageAttack = false; outbreakAttack = false; bounceAttack = false; } #endregion #region Stage 1 IEnumerator TripleSlash() { attacking = true; rb.velocity = Vector2.zero; anim.SetTrigger("Slash"); SlashAngle(); yield return new WaitForSeconds(1); anim.SetTrigger("Slash 2"); SlashAngle(); yield return new WaitForSeconds(1); anim.SetTrigger("Slash 3"); SlashAngle(); yield return new WaitForSeconds(1); ResetAllAttacks(); } void SlashAngle() { if (PlayerController.Instance.transform.position.x > transform.position.x || PlayerController.Instance.transform.position.x < transform.position.x) { Instantiate(slashEffect, SideAttackTransform); } else if (PlayerController.Instance.transform.position.y > transform.position.y) { SlashEffectAtAngle(slashEffect, 80, UpAttackTransform); } else if (PlayerController.Instance.transform.position.y < transform.position.y) { SlashEffectAtAngle(slashEffect, -90, DownAttackTransform); } } void SlashEffectAtAngle(GameObject _slashEffect, int _effectAngle, Transform _attackTransform) { _slashEffect = Instantiate(_slashEffect, _attackTransform); _slashEffect.transform.eulerAngles = new Vector3(0, 0, _effectAngle); _slashEffect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y); } IEnumerator Lunge() { Flip(); attacking = true; Physics2D.IgnoreLayerCollision(6, 7, true); anim.SetBool("Lunge", true); yield return new WaitForSeconds(1); damagePlayer = false; anim.SetBool("Lunge", false); Physics2D.IgnoreLayerCollision(6, 7, false); ResetAllAttacks(); } IEnumerator Parry() { attacking = true; rb.velocity = Vector2.zero; anim.SetBool("Parry", true); yield return new WaitForSeconds(0.8f); anim.SetBool("Parry", false); parrying = false; ResetAllAttacks(); } IEnumerator Slash() { attacking = true; rb.velocity = Vector2.zero; anim.SetTrigger("Slash"); SlashAngle(); yield return new WaitForSeconds(0.2f); ResetAllAttacks(); } #endregion #region Stage 2 void DiveAttackJump() { attacking = true; moveToPosition = new Vector2(PlayerController.Instance.transform.position.x, rb.position.y + 10); diveAttack = true; anim.SetBool("Jump", true); print("Starting Jump"); } public void Dive() { anim.SetBool("Dive", true); anim.SetBool("Jump", false); } public void DivingPillars() { Vector2 _impactPoint = groundCheckPoint.position; float _spawnDistance = 5; for (int i = 0; i < 10; i++) { Vector2 _pillarSpawnPointRight = _impactPoint + new Vector2(_spawnDistance, -0.25f); Vector2 _pillarSpawnPointLeft = _impactPoint - new Vector2(_spawnDistance, -0.25f); Instantiate(pillar, _pillarSpawnPointRight, Quaternion.Euler(0, 0, 0)); Instantiate(pillar, _pillarSpawnPointLeft, Quaternion.Euler(0, 0, 0)); Debug.Log("pillars spawned"); _spawnDistance += 7; } ResetAllAttacks(); } void BarrageBendDown() { attacking = true; rb.velocity = Vector2.zero; barrageAttack = true; anim.SetTrigger("BendDown"); } public IEnumerator Barrage() { rb.velocity = Vector2.zero; float _currentAngle = 30f; for (int i = 0; i < 10; i++) { GameObject _projectile = Instantiate(barrageFireball, transform.position, Quaternion.Euler(0, 0, _currentAngle)); if (facingRight) { _projectile.transform.eulerAngles = new Vector3(_projectile.transform.eulerAngles.x, 0, _currentAngle + 45); } else { _projectile.transform.eulerAngles = new Vector3(_projectile.transform.eulerAngles.x, 180, _currentAngle + 45); } _currentAngle = 5f; yield return new WaitForSeconds(0.4f); } yield return new WaitForSeconds(0.1f); anim.SetBool("Barrage", false); ResetAllAttacks(); } private void OnTriggerEnter2D(Collider2D _other) { if (_other.GetComponent<PlayerController>() != null && (diveAttack || bounceAttack)) { _other.GetComponent<PlayerController>().TakeDamage(damage * 2); PlayerController.Instance.pState.recoilingx = true; } if (_other.tag == "Player") { PlayerController.Instance.TakeDamage(damage); damagePlayer = true; } } #endregion #region Stage 3 void OutBreakBendDown() { attacking = true; rb.velocity = Vector2.zero; moveToPosition = new Vector2(DownAttackTransform.position.x, rb.position.y + 5); outbreakAttack = true; anim.SetTrigger("BendDown"); } public IEnumerator OutBreak() { yield return new WaitForSeconds(1f); anim.SetBool("Outbreak", true); rb.velocity = Vector2.zero; for (int i = 0; i < 20; i++) { Instantiate(barrageFireball, transform.position, Quaternion.Euler(0, 0, Random.Range(110, 130))); // down Instantiate(barrageFireball, transform.position, Quaternion.Euler(0, 0, Random.Range(50, 70))); // diagonal right Instantiate(barrageFireball, transform.position, Quaternion.Euler(0, 0, Random.Range(260, 200))); // diagonal left Debug.Log("Fireballs spawned"); yield return new WaitForSeconds(0.2f); } yield return new WaitForSeconds(0.1f); rb.constraints = RigidbodyConstraints2D.None; rb.constraints = RigidbodyConstraints2D.FreezeRotation; rb.velocity = new Vector2(rb.velocity.x, -10); yield return new WaitForSeconds(0.1f); anim.SetBool("Outbreak", false); ResetAllAttacks(); } void BounceAttack() { attacking = true; bounceCount = Random.Range(2, 5); BounceBendDown(); } int _bounces = 0; public void checkBounces() { if(_bounces < bounceCount - 1) { _bounces++; BounceBendDown(); } else { _bounces = 0; anim.Play("walk"); } } public void BounceBendDown() { rb.velocity = Vector2.zero; moveToPosition = new Vector2(PlayerController.Instance.transform.position.x, rb.position.y + 10); bounceAttack = true; anim.SetTrigger("BendDown"); } public void CalculateTargetAngle() { Vector3 _directionToTarget = (PlayerController.Instance.transform.position - transform.position).normalized; float _angleOfTarget = Mathf.Atan2(_directionToTarget.y, _directionToTarget.x) * Mathf.Rad2Deg; rotationDirectionToTarget = _angleOfTarget; } #endregion public override void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce) { sprite.material.color = alive ? Color.Lerp(Color.white, Color.white, Mathf.PingPong(Time.time * speed, 1.5f)) : Color.white; if (!stunned) { if (!parrying) { if (canStun) { hitCounter++; if(health == 17 || health == 12 || health == 6) { ResetAllAttacks(); StartCoroutine(Stunned()); } } base.EnemyHit(_damageDone, _hitDirection, _hitForce); if (currentEnemyState != EnemyStates.woodenBot_stage4)// parry isnt used in final form for a frantic ending { ResetAllAttacks(); StartCoroutine(Parry()); } } else { StopCoroutine(Parry()); ResetAllAttacks(); parrying = false; //parry attack StartCoroutine(Slash()); } } else { StopCoroutine(Stunned()); anim.SetBool("Stunned", false); stunned = false; } #region health to state if (health > 20) { ChangeState(EnemyStates.woodenBot_stage1); } if (health <= 18 && health > 10) { ChangeState(EnemyStates.woodenBot_stage2); } if (health <=13 && health > 5) { ChangeState(EnemyStates.woodenBot_stage3); } if (health <= 5 && health > 0) { ChangeState(EnemyStates.woodenBot_stage4); } if(health <= 0) { Death(0); } #endregion } public IEnumerator Stunned() { stunned = true; hitCounter = 0; anim.SetBool("Stunned", true); yield return new WaitForSeconds(6f); anim.SetBool("Stunned", false); stunned = false; } protected override void Death(float _destroyTime) { ResetAllAttacks(); alive = false; rb.velocity = new Vector2(rb.velocity.x, -25); anim.SetTrigger("Die"); } public void DestroyAfterDeath() { Destroy(gameObject); } }</code>
i tried making my game a zip file and sending it but it didnt work unfortunately! the email says the files too big or smth, sorry!
October 16, 2024 at 2:18 pm #16093::Sorry there’s actually a better way to check out what’s happening animation wise. Can I ask that you Record a video of the “Animator Window” instead of the “Console Window”. Make sure your Animation properties (where you can see your animation bools) are being shown as well.
Also have you already deactivated Looping for your jump animation?
Next, It appears that your boss is affected by gravity in the first video, but not in the second video. When your boss was stuck in the air in the second video, could you move him around and would he still fly to the wall? (If he does fly to the wall again, i want you to deactivate the wall while he’s in the air and see if he will complete the move)
I want you to remove the [HideInInspector] portion of [HideInInspector] public bool diveAttack; so that we can see if
ResetAllAttacks()
has occured in the first video.
How big are the files you tried to send? does your Google Drive not have enough space?
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: