Forum begins after the advertisement:


[part 5] mana image doesnt deplete after a scene transition

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [part 5] mana image doesnt deplete after a scene transition

Viewing 14 posts - 1 through 14 (of 14 total)
  • Author
    Posts
  • #12514
    Niyam Shah
    Participant

    my mana image doesnt show the mana decreasing after i transition to a different scene. IT will deplete in scene 1 but when i go to scene 2 my mana meter image will reset and won’t go down. However when i go back to scene 1, my mana meter will show the amount it should be.

    Ive assigned the mana prefab to my player character in all 3 scenes and have a canvas with mana in each scene. Did i miss something in the inspecotr?

    #12515
    Niyam Shah
    Participant

    also to be noted: when i load straight from scene 2, my mana image will deplete – only after transitioning from scene 1 to 2

    another wierd thing:

    when i start from scene 2 and transition to scene 1, then try to take damage, i wont take damage – an error occurs where it says im missing a game object which has been destroyed but im trying to access it — also if i try to use my up mana spell (the only mana spell i used) i will get stuck in the animation after my explosion effect occurs

    when i transition from scene 1 to scene 2 and back to scene 1, taking damage will cause all my hearts to dissapear and set my health instantly to zero

    rlly weird glitches

    #12516
    Niyam Shah
    Participant

    also idk if this helps but my heart containers will carry over scene transitions – just not the mana

    #12517
    Niyam Shah
    Participant

    these r errors i get when i get hit and instantly lose all my heart after going from scene1-scene2-scene1 getting hit

    #12518
    Niyam Shah
    Participant

    good news – i fixed the issue with the hearts by adding if(HeartContainers != null){} to the entire void start function and void updateheartsHUD of the heart container script

    #12519
    Niyam Shah
    Participant

    How i fixed my hearts

    using UnityEngine;
    using UnityEngine.UI;
    
    public class HeartController : MonoBehaviour
    {
        private GameObject[] heartContainers;
        private Image[] heartFills;
        public Transform heartsParent;
        public GameObject heartContainerPrefab;
        // Start is called before the first frame update
    
        void Start()
        {
    
                heartContainers = new GameObject[PlayerController.Instance.maxHealth];
                heartFills = new Image[PlayerController.Instance.maxHealth];
    
                PlayerController.Instance.onHealthChangedCallBack += UpdateHeartsHUD;
                InstantiateHeartContainers();
                UpdateHeartsHUD();
    
        }
    
        // Update is called once per frame
        void Update()
        {
    
        }
        void SetHeartContainers()
        {
            if (heartContainers != null)
            {
                for (int i = 0; i < heartContainers.Length; i++)
                {
                    if (i < PlayerController.Instance.maxHealth)
                    {
                        heartContainers[i].SetActive(true);
                    }
                    else
                    {
                        heartContainers[i].SetActive(false);
                    }
                }
                DontDestroyOnLoad(gameObject);
            }
    
        }
        void SetFilledHearts()
        {
            for (int i = 0; i < heartFills.Length; i++)
            {
                if (i < PlayerController.Instance.health)
                {
                    heartFills[i].fillAmount = 1;
                }
                else
                {
                    heartFills[i].fillAmount = 0;
                }
            }
        }
        void InstantiateHeartContainers()
        {
            for (int i = 0; i < PlayerController.Instance.maxHealth; i++)
            {
                GameObject temp = Instantiate(heartContainerPrefab);
                temp.transform.SetParent(heartsParent, false);
                heartContainers[i] = temp;
                heartFills[i] = temp.transform.Find("HeartFill").GetComponent<Image>();
            }
        }
        void UpdateHeartsHUD()
        {
            if(heartContainers != null)
            {
                SetHeartContainers();
                SetFilledHearts();
                DontDestroyOnLoad (gameObject);
            }
    
    
        }
    }
    #12520
    Niyam Shah
    Participant

    more random fun errors i found

    i actually dont knwo what these effect as my transitioning between scenes seem fine

    its just the mana thats the issue

    #12526
    Terence
    Keymaster

    Hi Niyam, can you show me your script for SceneTransition?

    #12528
    Niyam Shah
    Participant

    just so you know those errors i showed for my scene transition script arent happening anymore – still have a broken mana meter though

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    using UnityEngine.SceneManagement;
    
    public class SceneTransition : MonoBehaviour
    {
        [SerializeField] private string transitionTo; //Represents the scene to transition to
    
        [SerializeField] private Transform startPoint; //Defines the player's entry point in the scene
    
        [SerializeField] private Vector2 exitDirection; //Specifies the direction for the player's exit
    
        [SerializeField] private float exitTime; //Determines the time it takes for the player to exit the scene transition
    
        // Start is called before the first frame update
        private void Start()
        {
            if (GameManager.Instance.transitionedFromScene == transitionTo)
            {
                PlayerController.Instance.transform.position = startPoint.position;
    
                StartCoroutine(PlayerController.Instance.WalkIntoNewScene(exitDirection, exitTime));
            }
            StartCoroutine(UIManager.Instance.sceneFader.Fade(SceneFader.FadeDirection.Out));
        }
    
        private void OnTriggerEnter2D(Collider2D _other)
        {
            if (_other.CompareTag("Player"))
            {
                GameManager.Instance.transitionedFromScene = SceneManager.GetActiveScene().name;
    
                SceneManager.LoadScene(transitionTo);
    
                PlayerController.Instance.pState.cutscene = true;
    
                StartCoroutine(UIManager.Instance.sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, transitionTo));
            }
        }
    }
    #12531
    Terence
    Keymaster

    For your scene transition, it seems like this is the line that is the problem:

    StartCoroutine(UIManager.Instance.sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, transitionTo));

    You can do a debug log of UIManager.Instance and UIManager.Instance.sceneFader to see which is null.

    For your mana issue, check your character’s mana stat on the Inspector when playing. Does it decrease? If it does, then it means the mana stat is not properly linked to the UI on the new scene.

    #12533
    Niyam Shah
    Participant

    OK im not sure if its right but it fixed the issue:

    in scenes 2 and 3 i deleted the mana images from the canvas

    now when i go from scene 1 to 2 it stays

    i think the mana images were overlapping

    just wondering – when i load from scene 2 or 3 my mana wont appear and hearts are set to 0 – is there an easier method of doing what i did without making everything reset unless i start from scene 1

    #12534
    Niyam Shah
    Participant

    errors that happen when i load from scene 2 or 3

    as u can see it shows no hearts or mana container(i deleted mana container images in scene 2 and 3 because it was overlappign after a scene transition
    )

    #12536
    Niyam Shah
    Participant

    i tried using a debug log and it works but im still getting these errors at random places:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    using UnityEngine.SceneManagement;
    
    public class SceneTransition : MonoBehaviour
    {
        [SerializeField] private string transitionTo; //Represents the scene to transition to
    
        [SerializeField] private Transform startPoint; //Defines the player's entry point in the scene
    
        [SerializeField] private Vector2 exitDirection; //Specifies the direction for the player's exit
    
        [SerializeField] private float exitTime; //Determines the time it takes for the player to exit the scene transition
    
        // Start is called before the first frame update
        private void Start()
    
        {
            if (GameManager.Instance.transitionedFromScene == transitionTo)
            {
                PlayerController.Instance.transform.position = startPoint.position;
    
                StartCoroutine(PlayerController.Instance.WalkIntoNewScene(exitDirection, exitTime));
            }
    
            StartCoroutine(UIManager.Instance.sceneFader.Fade(SceneFader.FadeDirection.Out));
        }
    
        private void OnTriggerEnter2D(Collider2D _other)
        {
            if (_other.CompareTag("Player"))
            {
                GameManager.Instance.transitionedFromScene = SceneManager.GetActiveScene().name;
    
                SceneManager.LoadScene(transitionTo);
    
                PlayerController.Instance.pState.cutscene = true;
    
                StartCoroutine(UIManager.Instance.sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, transitionTo));
    
                Debug.Log("scene fader works");
            }
        }
    }
    using System.Collections;
    using System.Collections.Generic;
    using Unity.VisualScripting;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class PlayerController : MonoBehaviour
    {
        [Header("Horizontal Movement Settings")]
        [SerializeField] private float walkSpeed = 1;
        [Space(5)]
    
        [Header("Dash Settings")]
        [SerializeField] private float dashSpeed;
        [SerializeField] private float dashTime;
        [SerializeField] private float dashCooldown;
        [SerializeField] GameObject dashEffect;
        private bool canDash = true;
        private bool dashed;
        [Space(5)]
    
        [Header("Vertical Movement Settings")]
        [SerializeField] private float jumpForce = 45;
        private int jumpBufferCounter = 0;
        [SerializeField] private int jumpBufferFrames;
        private float coyoteTimeCounter = 0;
        [SerializeField] private float coyoteTime;
        [SerializeField] private float airJumpsCounter = 0;
        [SerializeField] private int maxAirJumps;
        [Space(5)]
    
        [Header("recoil")]
        [SerializeField] int recoilXSteps = 5;
        [SerializeField] int recoilYSteps = 5;
        [SerializeField] float recoilXSpeed = 100; 
        [SerializeField] float recoilYSpeed = 100;
        private int stepsXRecoiled, stepsYRecoiled;
        [Space(5)]
    
        [Header("Attack Settings")]
        private bool attack = false;
        private float timeBetweenAttack, timeSinceAttack;
        [SerializeField] Transform SideAttackTransform, BehindAttackTransform, UpAttackTransform, DownAttackTransform;
        [SerializeField] Vector2 SideAttackArea, BehindAttackArea, UpAttackArea, DownAttackArea;
        [SerializeField] LayerMask attackableLayer;
        [SerializeField] float damage;
        [SerializeField] GameObject slashEffect;
        [SerializeField] GameObject upSlashEffect;
        [SerializeField] GameObject downSlashEffect;
        bool restoreTime;
        float restoreTimeSpeed;
        [Space(5)]
    
        [Header("Ground Check Settings")]
        [SerializeField] private Transform groundCheckPoint;
        [SerializeField] private float groundCheckY = 0.2f;
        [SerializeField] private float groundCheckX = 0.5f;
        [SerializeField] private LayerMask whatIsGround;
        [Space(5)]
    
        [Header("Health")]
        public int health;
        public int maxHealth;
        [SerializeField] GameObject bloodSpurt;
        [SerializeField] GameObject crackeffect;
        [SerializeField] float hitFlashSpeed;
        public delegate void OnHealthChangedDelegate(); // delegate voids can be used on multiple methods
        [HideInInspector] public OnHealthChangedDelegate onHealthChangedCallBack;
        float healTimer;
        [SerializeField] float timeToHeal;
        [Space(5)]
    
        [Header("Mana settings")]
        [SerializeField] UnityEngine.UI.Image manaStorage;
        [SerializeField] float mana;
        [SerializeField] float manaDrainSpeed;
        [SerializeField] float manaGain;
        [Space(5)]
    
        [Header("Spell Settings")]
        //spell stats
        [SerializeField] float manaSpellCost;
        [SerializeField] float timeBetweenCast = 0.5f;
        float timeSinceCast;
        [SerializeField] float spellDamage; 
        //spell cast objects
        [SerializeField] GameObject upSpellExplosion;
        [Space(5)]
    
        [HideInInspector] public playerStatesList pState;
    
        private float xAxis, yAxis;
        private Rigidbody2D rb;
        private float gravity;
        private Animator anim;
        private SpriteRenderer sr;
    
    
    
        public static PlayerController Instance;
    
        private void Awake()
        {
            if(Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
    
            DontDestroyOnLoad(gameObject);
        }
    
    
    
        // Start is called before the first frame update
        void Start()
        {
            pState = GetComponent<playerStatesList>();
    
            rb = GetComponent<Rigidbody2D>();
    
            anim = GetComponent<Animator>();
    
            sr = GetComponent<SpriteRenderer>();
    
            gravity = rb.gravityScale;
    
            Mana = mana;
    
            manaStorage.fillAmount = Mana;
    
            Health = maxHealth;
    
        }
    
    
    
        //draw out hitboxes for basic attacks
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.red;
            Gizmos.DrawWireCube(SideAttackTransform.position, SideAttackArea);
            Gizmos.DrawWireCube(BehindAttackTransform.position, BehindAttackArea);
            Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea);
            Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea);
        }
    
    
    
        // Update is called once per frame
        void Update()
        {
            if (pState.cutscene) return;
    
            GetInputs();
            updateJumpVariable();
            RestoreTimeScale();
    
            if (pState.dashing) return;
            Flip();
            Move();
            Jump();
            StartDash();
            Attack();
            FlashWhileInvincible();
            Heal();
            CastSpell();
        }
        private void OnTriggerEnter2D(Collider2D _other) //for up and down cast spell
        {
            if (_other.GetComponent<Enemy>() != null && pState.casting)
            {
                _other.GetComponent<Enemy>().EnemyHit(spellDamage, (_other.transform.position - transform.position).normalized, -recoilYSpeed);
            }
        }
        private void FixedUpdate()
        {
            if (pState.cutscene) return;
    
            if (pState.dashing) return;
            Recoil();
        }
    
        //basic inputs for movement
        void GetInputs()
        {
            xAxis = Input.GetAxisRaw("Horizontal");
            yAxis = Input.GetAxisRaw("Vertical");
            attack = Input.GetButtonDown("Attack");
        }
    
    
    
        // flip player on x axis when left or right is picked
        void Flip()
        {
            if(xAxis < 0)
            {
                transform.localScale = new Vector2(-1, transform.localScale.y);
                pState.lookingRight = false;
            }
    
            else if(xAxis > 0)
            {
                transform.localScale = new Vector2(1, transform.localScale.y);
                pState.lookingRight = true;
            }
    
            
        }
    
    
    
        //move left and right
        private void Move()
        {
            rb.velocity = new Vector2(walkSpeed * xAxis, rb.velocity.y);
            anim.SetBool("walking", rb.velocity.x != 0 && Grounded());
        }
    
    
    
        //allows for dashing and air dashing
        void StartDash()
        {
            if(Input.GetButtonDown("Dash") && canDash && !dashed)
            {
                StartCoroutine(Dash());
                dashed = true;
            }
    
            if (Grounded())
            {
                dashed = false;
            }
        }
        //stops middair infinite dashing
        IEnumerator Dash()
        {
            canDash = false;
    
            pState.dashing = true;
    
            anim.SetTrigger("Dashing");
    
            rb.gravityScale = 0;
    
            int _dir = pState.lookingRight ? 1 : -1;
    
            rb.velocity = new Vector2(_dir * dashSpeed, 0);
            if (Grounded()) Instantiate(dashEffect, transform);
    
            yield return new WaitForSeconds(dashTime);
    
            rb.gravityScale = gravity;
    
            pState.dashing = false;
    
            yield return new WaitForSeconds(dashCooldown);
    
            canDash = true;
        }
    
    
        public IEnumerator WalkIntoNewScene(Vector2 _exitDir, float _delay)
        {
            //if you exit upwards
            if(_exitDir.y > 0)
            {
                rb.velocity = jumpForce * _exitDir;
            }
    
            //horizontal exiting
            if(_exitDir.x != 0)
            {
                xAxis = _exitDir.x > 0 ? 1 : -1;
    
                Move();
            }
    
            Flip();
            yield return new WaitForSeconds(_delay);
            pState.cutscene = false;
        }
    
    
        //create hitboxes for attacks
        void Attack()
        {
            timeSinceAttack += Time.deltaTime;
            if(attack && timeSinceAttack >= timeBetweenAttack)
            {
    
                timeSinceAttack = 0;
    
    
                //side attack
                if (yAxis == 0 || yAxis < 0 && Grounded())
                {
                    Hit(SideAttackTransform, SideAttackArea, ref pState.recoilingx, recoilXSpeed);
                    Instantiate(slashEffect, SideAttackTransform);
                    anim.SetTrigger("Attacking");
    
                }
    
                //up air attack
                else if (yAxis > 0 && !Grounded())
                {
                    Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingy, recoilYSpeed);
                    Instantiate(upSlashEffect, UpAttackTransform);
                    anim.SetTrigger("Attacking");
                }
    
                //down air attak
                else if (yAxis < 0 && !Grounded())
                {
                    Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingy, recoilYSpeed);
                    Instantiate(downSlashEffect, DownAttackTransform);
                    anim.SetTrigger("Attacking");
                }
    
                if (yAxis > 0 && Grounded())
                {
                    Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingy, recoilYSpeed);
                    Instantiate(upSlashEffect, UpAttackTransform);
                    anim.SetTrigger("upAttack");
                }
            }
    
        }
    
    
    
        //hitting the enemy and adding recoil to attacks
        void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilDir, float _recoilStrength)
        {
            Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);
    
            if(objectsToHit.Length > 0)
            {
                _recoilDir = true;  
            }
    
            for(int i = 0; i < objectsToHit.Length; i++)
            {
                if (objectsToHit[i].GetComponent<Enemy>() != null)
                {
                    objectsToHit[i].GetComponent<Enemy>().EnemyHit
                        (damage, (transform.position - objectsToHit[i].transform.position).normalized, _recoilStrength);
    
                    if (objectsToHit[i].CompareTag("Enemy"))
                    {
                        Mana += manaGain;
                    }
                }
            }
        }
    
    
    
        //changes the direction of attack based on aerial positions
        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);
        }
    
        void UpSlashEffectAtAngle(GameObject _upSlashEffect, int _effectAngle, Transform _attackTransform)
        {
            _upSlashEffect = Instantiate(_upSlashEffect, _attackTransform);
            _upSlashEffect.transform.eulerAngles = new Vector3(0, 0, _effectAngle);
            _upSlashEffect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y);
        }
    
        void DownSlashEffectAtAngle(GameObject _downSlashEffect, int _effectAngle, Transform _attackTransform)
        {
            _downSlashEffect = Instantiate(_downSlashEffect, _attackTransform);
            _downSlashEffect.transform.eulerAngles = new Vector3(0, 0, _effectAngle);
            _downSlashEffect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y);
        }
    
    
    
        //directional player recoil based on main slash attacks, x and y axis movement
        void Recoil()
        {
            //recoiling in the x axis
            if (pState.recoilingx)
            {
                if (pState.lookingRight)
                {
                    rb.velocity = new Vector2(-recoilXSpeed, 0);
                }
                else
                {
                    rb.velocity = new Vector2(recoilXSpeed, 0);
                }
            }
    
            //recoil in the y axis
            if (pState.recoilingy)
            {
                rb.gravityScale = 0;
                if (yAxis < 0)
                {
                    rb.velocity = new Vector2(rb.velocity.x, recoilYSpeed);
                }
                else
                {
                    rb.velocity = new Vector2(rb.velocity.x, -recoilYSpeed);
                }
                airJumpsCounter = 0;
            }
            else
            {
                rb.gravityScale = gravity;
            }
    
            //stop recoiling
    
            if (pState.recoilingx && stepsXRecoiled < recoilXSteps)
            {
                stepsXRecoiled++;
            }
    
            else
            {
                StopRecoilX();
            }
    
            if (pState.recoilingy && stepsYRecoiled < recoilYSteps)
            {
                stepsYRecoiled++;
            }
    
            else
            {
                StopRecoilY();
            }
    
            if (Grounded())
            {
                StopRecoilY();
            }
        }
        
    
        //stop recoiling forever
        void StopRecoilX()
        {
            stepsXRecoiled = 0;
            pState.recoilingx = false;
        }
        void StopRecoilY()
        {
            stepsYRecoiled = 0;
            pState.recoilingy = false;
        }
    
    
    
        //take damage, set health and gives some invinicibility frames
        public void TakeDamage(float _damage)
        {
            Health -= Mathf.RoundToInt(_damage);
            StartCoroutine(StopTakingDamage());
        }
    
        IEnumerator StopTakingDamage()
        {
            pState.invincible = true;
            anim.SetTrigger("takeDamage");
            GameObject _bloodSpurtParticles = Instantiate(bloodSpurt, transform.position, Quaternion.identity);
            GameObject _crack = Instantiate(crackeffect, transform.position, Quaternion.identity);
            Destroy(_crack, 0.1f);
            Destroy(_bloodSpurtParticles, 1.5f);
            yield return new WaitForSeconds(1f);
            pState.invincible = false;
        }
    
        //flash black and white when hit for i frames
        void FlashWhileInvincible()
        {
            sr.material.color = pState.invincible ?
                Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time * hitFlashSpeed, 1.5f)) : Color.white;
        }
    
        void RestoreTimeScale()
        {
            if (restoreTime)
            {
                if (Time.timeScale < 1)
                {
                    Time.timeScale += Time.deltaTime * restoreTimeSpeed;
                }
                else
                {
                    Time.timeScale = 1;
                    restoreTime = false;
                }
            }
        }
    
    
        //create invincibility frames
        public void HitStopTime(float _newTimeScale, int _restoreSpeed, float _delay)
        {
            restoreTimeSpeed = _restoreSpeed;
            Time.timeScale = _newTimeScale;
    
            if (_delay > 0)
            {
                StopCoroutine(StartTimeAgain(_delay));
                StartCoroutine(StartTimeAgain(_delay));
            }
            else
            {
                restoreTime = true;
            }
        }
    
    
        //begin taking damage again
        IEnumerator StartTimeAgain(float _delay)
        {
            restoreTime = true;
            yield return new WaitForSeconds(_delay);
        }
    
    
        //health and removing health
        public int Health
        {
            get { return health; }
            set
            {
                if (health != value)
                {
                    health = Mathf.Clamp(value, 0, maxHealth);
    
    
                    if (onHealthChangedCallBack != null)
                    {
                        onHealthChangedCallBack.Invoke();
                    }
                }
            }
        }
    
    
    
        //heal with mana with a
        void Heal()
        {
            if (Input.GetButton("Heal") && Health < maxHealth && Mana > 0 && !pState.jumping && !pState.dashing)
            {
                pState.healing = true;
                anim.SetBool("Healing", true);
    
                //healing
                healTimer += Time.deltaTime;
                if (healTimer >= timeToHeal)
                {
                    Health++;
                    healTimer = 0;
                }
    
                //drain mana
                Mana -= Time.deltaTime * manaDrainSpeed;
            }
            else
            {
                pState.healing = false;
                anim.SetBool("Healing", false);
                healTimer = 0;
            }
        }
    
        //create mana
        float Mana
        {
            get { return mana; }
            set
            {
                //if mana stats change
                if (mana != value)
                {
                    mana = Mathf.Clamp(value, 0, 1);
                    manaStorage.fillAmount = Mana;
                }
            }
        }
    
       
    
        //cast up spell explosion when u have enough mana and its been a long time since your last kaboom
        void CastSpell()
        {
    
            if (Input.GetButtonDown("CastSpell") && timeSinceCast >= timeBetweenCast && Mana >= manaSpellCost && yAxis > 0)
            {
                pState.casting = true;
                timeSinceCast = 0;
                StartCoroutine(CastCoroutine());
            }
            else
            {
                timeSinceCast += Time.deltaTime;
            }
        }
        IEnumerator CastCoroutine()
        {
            anim.SetBool("Casting", true);
            yield return new WaitForSeconds(0.2f);
            //up cast
            if (yAxis > 0)
            {
                Instantiate(upSpellExplosion, transform);
                rb.velocity = Vector2.zero;
            }
    
            Mana -= manaSpellCost;
            yield return new WaitForSeconds(0.2f);
            anim.SetBool("Casting", false);
            pState.casting = false;
        }
    
    
        //checks if you are grounded
        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;   
            }
        }
    
    
    
        //makes you jump when pressing spacebar
        void Jump()
        {
    
            if (jumpBufferCounter > 0 && coyoteTimeCounter > 0 && !pState.jumping)
            {
                rb.velocity = new Vector3(rb.velocity.x, jumpForce);
    
                pState.jumping = true;
            }
            
            if (!Grounded() && airJumpsCounter < maxAirJumps && Input.GetButtonDown("Jump"))
            {
                pState.jumping = true;
    
                airJumpsCounter++;
    
                rb.velocity = new Vector3(rb.velocity.x, jumpForce);
    
            }
    
            if (Input.GetButtonUp("Jump") && rb.velocity.y > 3)
            {
                rb.velocity = new Vector2(rb.velocity.x, 0);
    
                pState.jumping = false;
            }
    
            //animate jumping double jump and falling animation
    
            anim.SetBool("jumping", !Grounded() && rb.velocity.y > -15 && airJumpsCounter == 0);
    
            anim.SetBool("doublejump", !Grounded() && airJumpsCounter == 1);
    
    
            anim.SetBool("falling", !Grounded() && rb.velocity.y < -10);
    
        }
    
    
    
        //coyote time and jump buffering
        void updateJumpVariable()
        {
            //coyote time
            if (Grounded())
            {
                pState.jumping = false;
                coyoteTimeCounter = coyoteTime;
                airJumpsCounter = 0;
            }
            else
            {
                coyoteTimeCounter -= Time.deltaTime;
            }
    
    
            //jump buffering
            if (Input.GetButtonDown("Jump"))
            {
                jumpBufferCounter = jumpBufferFrames;
            }
            else
            {
                jumpBufferCounter--;
            }
        }
    }
    #12539
    Terence
    Keymaster

    For NullReferenceExceptions, you can refer to this video to learn how to rectify them:

    I suggest you move on with the series first, as some of the bugs you are running into will be fixed in the later videos. As long as your game runs, it is fine.

Viewing 14 posts - 1 through 14 (of 14 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: