Forum begins after the advertisement:


[General] About GetButton and GetButtonDown

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [General] About GetButton and GetButtonDown

Viewing 14 posts - 1 through 14 (of 14 total)
  • Author
    Posts
  • #15590
    MI NI
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    Hello, I have another question to ask. Regarding my previous suggestion that I want to change the opening method of the map and inventory so that it can be enabled without pressing the button, you gave me some suggestions, but I encountered a Problems I can’t explain. In terms of teaching, your approach is to use GetButton to keep it on every frame until you release the button. Logically speaking, if I change it to GetButtonDown, the effect should be as long as the frame is pressed. In response, I used GetButtonDown to successfully create a map switch, but when I used the same method in the inventory, it did not work. I initially suspected that there was a problem with the inventory code, but after checking, I found that only GetButton( "inventory") will work, GetButtonDown("inventory") cannot produce any output, I even simplified it to no judgment, leaving only if(GetButtonDown("inventory")) Debug.Log("BP_1" ) ;
    It still doesn’t output anything, but if I change it to if(GetButton("inventory"))Debug.Log("BP_1"); there is output.
    I tried adding a new inputManager button but still the same result.
    I recorded a video as a reference for the above question. I was wondering what you think, I’m wondering maybe my Unity is broken, is there any way to detect it?

    I don’t know if you need my code, I think it’s a small problem but I still don’t know what the problem is, if you need more information, please do let me know

    #15595
    Terence
    Keymaster
    Helpful?
    Up
    0
    ::

    Is your input detection code in Update()? GetButtonDown() only triggers for 1 frame, and is sync-ed to Update(). So if you are on a function like OnTriggerStay2D() (which is not sync-ed to Update()), it is possible to miss that frame.

    #15598
    MI NI
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    My code is indeed placed in Update(). What should I do to fix it? In addition, I would like to know if one of the GetButtonDown() in the same GetInputs() can be used but the other cannot. ?That doesn’t make sense to me,
    If it’s something to do with the inventory function that’s causing this problem, then when I create the new InputMananger button it at least has output, but it doesn’t, maybe that’s normal in the program, I don’t know. I need some advice

    #15599
    Terence
    Keymaster
    Helpful?
    Up
    0
    ::

    It’s difficult to tell what’s wrong from the video. This seems like a problem caused by your project setup, so there can be a lot of causes for this.

    Have you tried pasting your code into ChatGPT? What does it say?

    #15600
    MI NI
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    thank you for your help
    , I posted the file to ChatGpt and it gave me an error to troubleshoot. After trial and error, I found that the stock buttons, Type and Axis in my InputManager were different from other buttons. I changed them to be the same as other buttons and it worked normally.

    #15603
    Terence
    Keymaster
    Helpful?
    Up
    0
    ::

    MI NI, I don’t quite understand what you mean. Would you mind sharing your ChatGPT conversation here? I am interested to find out what your issue was.

    #15604
    MI NI
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    The framed parts in the picture are the parts I modified. They were originally
    Type Joystick Axis
    Axis 6th asix

    I seem to be unable to share my GPT conversation in the article, but it is still in the article when I edit it. Maybe you can edit my article to view the URL, or I can send you an email.

    https://chatgpt.com/share/4eb1584d-1118-42c7-a008-c26dc86cb14e

    View post on imgur.com

    #15615
    Joseph Tang
    Moderator
    Helpful?
    Up
    0
    ::

    Hi MI NI can I ask that you open up the Hierarchy to check the in scene Inventory and take a video of you using the inventory using your new switch method and the original code? (To check if the inventory is activated or not), and can you post your code for both the PlayerController.cs and InventoryManager.cs?

    #15624
    MI NI
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    This is my video and code.

    PlayerController.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UIElements;
    using UnityEngine.UI;
    
    public class PlayerController : MonoBehaviour
    {
        [Header("水平移動")]
        [SerializeField] private float walkSpeed = 1; //走路速度
        [Space(5)]
    
        [Header("垂直移動")]
        [SerializeField] private float jumpForce = 45; //跳躍速度
        private int jumpBufferCounter = 0; //按下按鈕儲存指令
        [SerializeField] private int jumpBufferFrames; //按下按鈕儲存指令時間/偵
        private float coyoteTimeCounter = 0; //土狼時間
        [SerializeField] private float coyoteTime; //土狼時間/偵
        private int airJumpCounter = 0;
        [SerializeField] private int maxAirJumps;
    
        [SerializeField] private float fallMultiplier = 2.5f;
        [SerializeField] private float lowJumpMulitiplier = 2f;
    
        [Space(5)]
    
        [Header("WallJump")]
        [SerializeField] private float wallSlidingSpeed; //滑行速度
        [SerializeField] private Transform wallCheck; //牆壁檢查點
        [SerializeField] private LayerMask wallLayer;
        [SerializeField] private float wallJumpingDuration; //蹬牆跳持續時間
        [SerializeField] private Vector2 wallJumpPower;
        float wallJumpingDirection;
        bool isWallSliding;
        bool isWallJumping;
        [Space(5)]
    
        [Header("地面檢查")]
        [SerializeField] private Transform groundCheckPoint; //地面檢查點
        [SerializeField] private float groundCheckY = 0.2f; //
        [SerializeField] private float groundCheckX = 0.5f; //
        [SerializeField] private LayerMask whatIsGround; //檢查是否在地面
        [Space(5)]
    
        [Header("衝刺")]
        [SerializeField] private float dashSpeed; //衝刺速度
        [SerializeField] private float dashTime;  //衝刺時間
        [SerializeField] private float dashCooldown; //衝刺冷卻
        [Space(5)]
    
        [Header("攻擊")]
    
        [SerializeField] private float timeBetweenAttack; //攻擊時間
        [SerializeField] Transform SideAttackTransform, UpAttackTransform, DownAttackTransform; //不同方向攻擊位置
        [SerializeField] Vector2 SideAttackArea, UpAttackArea, DownAttackArea; //不同方向攻擊範圍
        [SerializeField] LayerMask attackableLayer; //可攻擊的對象圖層
        [SerializeField] float damage; //傷害
        [SerializeField] GameObject slashEffect; //劍氣效果
        private bool attack = false;
        private float timeSinceAttack;
    
        bool restoreTime;
        public float restoreTimeSpeed;
    
        [Space(5)]
    
        [Header("後座力")]
        [SerializeField] int recilXSteps = 5;
        [SerializeField] int recilYSteps = 5;
        [SerializeField] float recilXSpeed = 5;
        [SerializeField] float recilYSpeed = 5;
    
        private int stepsXRecoiled, stepsYRecoiled;
        [Space(5)]
    
        [Header("血量")]
        public float health;  //當前血量
        public float maxHealth; //最大血量
        [SerializeField] GameObject hitEffect; //被擊效果
        [SerializeField] float hitFlashSpeed; //受傷角色閃爍
        float healTimer;
        [SerializeField] float timeToheal;
        [Space(5)]
    
        [Header("血量圖片")]
        public Text healthText; //血量文字
        public UnityEngine.UI.Image healthImage; //血量圖片
        public UnityEngine.UI.Image healthEffect; //血量緩衝特效
        public float effectTime = 0.5f; //緩衝持續時間
        private Coroutine updateCoroutine;
        [Space(5)]
    
        [Header("魔力")]
        [SerializeField] float mana; //魔力量
        [SerializeField] float maxMana; //最大魔力量
        [SerializeField] float manaDrainSpeed; //魔力消耗速度
        [SerializeField] float manaGain; //獲得魔力
        [SerializeField] UnityEngine.UI.Image manaImage; //魔力圖片
    
        [Header("技能")]
        [SerializeField] float manaSpellCost = 0.3f; //法術消耗
        [SerializeField] float timeBetweenCast = 0.5f; //攻擊間隔速度
        [SerializeField] GameObject sideSpellFireball; //火球物件Prefab
        float timeSinceCast;
        float castOrHealtimer;
    
        [Header("相機")]
        [SerializeField] private float playerFallSpeedTheshold = -10;
    
        [HideInInspector] public PlayerStateList pState; //取得緩衝輸入腳本
        [HideInInspector] public Rigidbody2D rb;
        private Animator anim;
        private SpriteRenderer sr;
    
        private float gravity; //重力
        private float xAxis, yAxis; //取得XY軸輸入
        private bool canDash = true;
        private bool dashed;
        private bool canFlash = true;
        public bool openMap = false; //開啟地圖
        public bool openInventory = false; //開啟背包
    
        //解鎖能力
        public bool unlockWallJump;
        public bool unlockDash;
        public bool unlockAirJump;
        public bool unlockSideSpell = false;
    
        public static PlayerController Instance; //防止多個重複的玩家腳本出現
        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
    
            DontDestroyOnLoad(gameObject);
    
        }
    
        void Start()
        {
            pState = GetComponent<PlayerStateList>();
    
            rb = GetComponent<Rigidbody2D>();
    
            sr = GetComponent<SpriteRenderer>();
    
            anim = GetComponent<Animator>();
    
            gravity = rb.gravityScale;
    
            Health = maxHealth; //Save之後不再需要
            Mana = maxMana;
    
            healthImage.fillAmount = health / maxHealth;
            healthEffect.fillAmount = health / maxHealth;
            healthText.text = health.ToString() + "/" + maxHealth.ToString();
            manaImage.fillAmount = Mana;
    
            
    
            if (Health == 0)
            {
                pState.alive = false;
                GameManager.Instance.RespawnPlayer();
            }
    
            SaveData.Instance.LoadPlayerData();
        }
    
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.red;
            Gizmos.DrawWireCube(SideAttackTransform.position, SideAttackArea);
            Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea);
            Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea);
            //Gizmos.DrawWireCube(wallCheck.position, )
        }
    
        void Update()
        {
            if (GameManager.Instance.gameIsPaused) return;
    
            RestoreTimeScale();
    
            if (pState.cutscene) return;
            if (pState.alive)
            {
                GetInputs();
                ToggleMap();
                ToggleInventory();
            }
            UpdateJumpVariables();
            RestoreTimeScale();
            UpdateCameraYDampForPlayerFall();
    
            if (pState.alive)
            {
                Heal();
            }
    
            if (pState.dashing || pState.healing) return;
    
            if (pState.alive)
            {
                if (!isWallJumping)
                {
                    Flip();
                    Move();
                    Jump();
                }
                if (unlockWallJump)
                {
                    WallSlide();
                    WallJump();
                }
                if (unlockDash)
                {
                    StartDash();
                }
    
                Attack();
                CastSpell();
            }
            FlashWhileInvincible();
        }
    
        private void FixedUpdate()
        {
            if (pState.cutscene) return;
    
            if (pState.dashing || pState.healing) return;
            Recoil();
     
        }
    
        void GetInputs() //獲取輸入
        {
            xAxis = Input.GetAxisRaw("Horizontal");
            yAxis = Input.GetAxisRaw("Vertical");
            attack = Input.GetButtonDown("Attack");
    
            //地圖Map Key:M
            if (Input.GetButtonDown("Map") && !openMap)
            {
                openMap = true;
            }
            else if(Input.GetButtonDown("Map") && openMap)
            {
                openMap = false;
            }
    
            //背包Inventory Key:I
            if (Input.GetButtonDown("Inventory") && !openInventory)
            {
                openInventory = true;
            }
            else if (Input.GetButtonDown("Inventory") && openInventory)
            {
                openInventory = false;
            }
            
    
            if (Input.GetButton("Cast/Heal"))
            {
                castOrHealtimer += Time.deltaTime;
            }
            
        }
    
        void ToggleMap()
        {
            if(openMap)
            {
                UIManager.Instance.mapHandler.SetActive(true);
            }
            else
            {
                UIManager.Instance.mapHandler.SetActive(false);
            }
        }
    
        void ToggleInventory()
        {
            if (openInventory)
            {
                UIManager.Instance.inventory.SetActive(true);
            }
            else
            {
                UIManager.Instance.inventory.SetActive(false);
            }
        }
    
        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;
            }
        }
    
        private void Move() //移動
        {
            if (pState.healing) rb.velocity = new Vector2(0, 0); //如果玩家正在治療則無法移動
            rb.velocity = new Vector2(walkSpeed * xAxis ,rb.velocity.y);
            anim.SetBool("Walk", rb.velocity.x !=0 && Grounded());
        }
    
        void UpdateCameraYDampForPlayerFall()
        {
            //if falling past a certain speed threshold
            if (rb.velocity.y < playerFallSpeedTheshold && !CameraManager.Instance.isLerpingYDamp && !CameraManager.Instance.hasLerpingYDamping)
            {
                StartCoroutine(CameraManager.Instance.LerpYDamping(true));
            }
            //if standing stil or moveing up
            if(rb.velocity.y >= 0 && !CameraManager.Instance.isLerpingYDamp && CameraManager.Instance.hasLerpingYDamping)
            {
                //reset camera funtion
                CameraManager.Instance.hasLerpingYDamping = false;
                StartCoroutine(CameraManager.Instance.LerpYDamping(false));
            }
        }
    
        void StartDash() //衝刺
        {
            if(Input.GetButtonDown("Dash") && canDash && !dashed)
            {
                StartCoroutine(Dash());
                dashed = true;
            }
    
            if(Grounded())
            {
                dashed = false;
            }
        }
    
        IEnumerator Dash()
        {
            canDash = false; 
            pState.dashing = true;
            anim.SetTrigger("Dash");
            rb.gravityScale = 0;
            int _dir = pState.lookingRight ? 1 : -1;
            rb.velocity = new Vector2(_dir * dashSpeed, 0);
            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) //過場動畫
        {
            pState.invincible = true;
    
            if(_exitDir.y > 0) //如果退出位置為向上
            {
                rb.velocity = jumpForce * _exitDir;
            }
    
            //如果退出位置為水平移動
            if(_exitDir.x != 0)
            {
                xAxis = _exitDir.x > 0 ? 1 : -1;
    
                Move();
            }
    
            Flip();
            yield return new WaitForSeconds(_delay);
            pState.invincible = false;
            pState.cutscene = false;
    
        }
    
        void Attack() //攻擊
        {
            timeSinceAttack += Time.deltaTime;
            if(attack && timeSinceAttack >= timeBetweenAttack)
            {
                timeSinceAttack = 0;
                anim.SetTrigger("Attack");
    
                if(yAxis == 0 || yAxis < 0 && Grounded()) //如果玩家在地面上且沒有按住"上",正常攻擊
                {
                    int _recoilLeftOrRight = pState.lookingRight ? 1 : -1; 
    
                    Hit(SideAttackTransform, SideAttackArea, ref pState.recoilingX, Vector2.right * _recoilLeftOrRight, recilXSpeed);
                    Instantiate(slashEffect, SideAttackTransform);
                }
                else if(yAxis > 0) //如果按住"上",上攻擊
                {
                    Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingY, Vector2.up, recilYSpeed);
                    SlashEffectAtAngle(slashEffect, 90, UpAttackTransform);
                }
                else if (yAxis < 0 && !Grounded()) //如果不在地面且按住"下",下攻擊
                {
                    Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingY, Vector2.down, recilYSpeed);
                    SlashEffectAtAngle(slashEffect, -90, DownAttackTransform);
                }
    
            }
        }
    
        private void Hit(Transform _attackTransfrom, Vector2 _attackArea, ref bool _recoilBool,Vector2 _recoilDir , float _recoilStrength) //給予傷害
        {
            Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransfrom.position, _attackArea, 0, attackableLayer);
            List<Enemy> hitEnemise = new List<Enemy>();
    
            if(objectsToHit.Length > 0)
            {
                //Debug.Log("Hit");
                _recoilBool = true;
    
            }
            for(int i = 0; i < objectsToHit.Length; i++)
            {
                if(objectsToHit[i].GetComponent<Enemy>() != null)
                {
                    objectsToHit[i].GetComponent<Enemy>().EnemyHit(damage, _recoilDir , _recoilStrength)  ;
                    /*
                    Enemy e = objectsToHit[i].GetComponent<Enemy>();
                    if(e && !hitEnemise.Contains(e))
                    {
                        e.EnemyHit(damage, (transform.position - objectsToHit[i].transform.position).normalized, _recoilStrength);
                        hitEnemise.Add(e);
                    }
                    */
                    if (objectsToHit[i].CompareTag("Monster")) //打到怪物增加魔力
                    {
                        Mana += manaGain;
                    }
                }
            }
        }
        
        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 Recoil() //反衝
        {
            if(pState.recoilingX)
            {
                if (pState.lookingRight)
                {
                    rb.velocity = new Vector2(-recilXSpeed, 0);
                }
                else
                {
                    rb.velocity = new Vector2(recilXSpeed, 0);
                }
            }
    
            if(pState.recoilingY)
            {
                rb.gravityScale = 0;
                if (yAxis < 0)
                {
                    rb.velocity = new Vector2(rb.velocity.x, recilYSpeed);
                }
                else
                {
                    rb.velocity = new Vector2(rb.velocity.x, -recilYSpeed);
                }
    
                airJumpCounter = 0;
    
            }
            else
            {
                rb.gravityScale = gravity;
            }
            
            //Stop recoil 停止反衝
            if(pState.recoilingX && stepsXRecoiled < recilXSteps)
            {
                stepsXRecoiled++;
            }
            else
            {
                StopRecoilX();
            }
    
            if (pState.recoilingY && stepsYRecoiled < recilYSteps)
            {
                stepsYRecoiled++;
            }
            else
            {
                StopRecoilY();
            }
    
            if(Grounded())
            {
                StopRecoilY();
            }
    
        }
    
        void StopRecoilX()
        {
            stepsXRecoiled = 0;
            pState.recoilingX = false;
        }
        void StopRecoilY()
        {
            stepsYRecoiled = 0;
            pState.recoilingY = false;
        }
    
        public void TakeDamage(float _damage) //玩家受傷
        {
            if(pState.alive)
            {
                Health -= Mathf.RoundToInt(_damage);
                if(Health <= 0)
                {
                    Health = 0;
                    StartCoroutine(Death());
                }
                else
                {
                    StartCoroutine(StopTakingDamage());
    
                    healthImage.fillAmount = health / maxHealth; //血量圖片
                    healthText.text = health.ToString() + "/" + maxHealth.ToString(); //血量文字
    
                    if (updateCoroutine != null)
                    {
                        StopCoroutine(updateCoroutine);
                    }
                    updateCoroutine = StartCoroutine(UpdateHealthEffect());
                } 
            }
        }
    
        private IEnumerator UpdateHealthEffect() //血量緩降協程
        {
            float effectLength = healthEffect.fillAmount - healthImage.fillAmount;
            float elapsedTime = 0f;
    
            while (elapsedTime < effectTime && effectLength != 0)
            {
                elapsedTime += Time.deltaTime;
                healthEffect.fillAmount = Mathf.Lerp
                (healthImage.fillAmount + effectLength, healthImage.fillAmount, elapsedTime / effectTime);
                yield return null;
            }
            healthEffect.fillAmount = healthImage.fillAmount;
        }
    
        public IEnumerator StopTakingDamage() //無敵偵
        {
            pState.invincible = true;
            GameObject _hitEffect = Instantiate(hitEffect, transform.position, Quaternion.identity);
            Destroy(_hitEffect, 1.5f);
            anim.SetTrigger("Hurt");
            yield return new WaitForSeconds(1f);
            pState.invincible = false;
        }
    
        IEnumerator Flash()
        {
            sr.enabled = !sr.enabled;
            canFlash = false;
            yield return new WaitForSeconds(0.2f);
            canFlash = true;
        }    
    
        void FlashWhileInvincible()
        {
            //將渲染改為"PingPongLerp" 如果玩家是無敵狀態則將其從白色改為黑色 否則將玩家設定為白色
            //sr.material.color = pState.invincible ? Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time * hitFlashSpeed, 1.0f)) : Color.white;
            if(pState.invincible && !pState.cutscene)
            {
                if (Time.timeScale > 0.2f && canFlash) 
                {
                    StartCoroutine(Flash()); 
                }
            }
            else
            {
                sr.enabled = true;
            }
        }
    
        void RestoreTimeScale() //受傷暫停時間
        {
            if(restoreTime) //檢查是否為真
            {
                if(Time.timeScale < 1) //如果小於1 時間速度加快到達1
                {
                    Time.timeScale += Time.unscaledDeltaTime * restoreTimeSpeed;
                }
                else //如果超過1 時間為1
                {
                    Time.timeScale = 1;
                    restoreTime = false;
                }
            }
        }
    
        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;
            }
        }
    
        IEnumerator StartTimeAgain(float _delay)
        {
            yield return new WaitForSecondsRealtime(_delay);
            restoreTime = true;
        }
    
        IEnumerator Death()
        {
            pState.alive = false;
            Time.timeScale = 1f; //避免受傷暫停時間導致出錯
            //可在此呼叫粒子效果
            anim.SetTrigger("Death");
    
            rb.constraints = RigidbodyConstraints2D.FreezePosition;
            rb.constraints = RigidbodyConstraints2D.FreezeRotation;
            GetComponent<BoxCollider2D>().enabled = false;
    
            yield return new WaitForSeconds(0.9f);
            StartCoroutine(UIManager.Instance.ActiveDeathScreen());
        }
    
        public void Respawned()
        {
            if(!pState.alive)
            {
                rb.constraints = RigidbodyConstraints2D.None;
                rb.constraints = RigidbodyConstraints2D.FreezeRotation;
                GetComponent<BoxCollider2D>().enabled = true;
    
                pState.alive = true;
                Health = maxHealth;
                anim.Play("PlayerIdle");
            }
        }
    
        public float Health //血量
        {
            get { return health; }
            set
            {
                if(health != value)
                {
                    health = Mathf.Clamp(value, 0, maxHealth);
    
                }
            }
        }
    
        void Heal()
        {
            if(Input.GetButton("Cast/Heal") && castOrHealtimer > 0.5f && health < maxHealth && Mana > 0 && Grounded() && !pState.dashing)
            {
                pState.healing = true;
                anim.SetBool("Heal", true);
    
                //補血
                healTimer += Time.deltaTime;
                if(healTimer >= timeToheal)
                { 
                    health += 5; //恢復血量
                    healTimer = 0; //血量計時器
                    healthImage.fillAmount = health / maxHealth; //血量圖片
                    healthEffect.fillAmount = health / maxHealth; //血量效果圖片
                    healthText.text = health.ToString() + "/" + maxHealth.ToString(); //血量文字
                }
                Mana -= Time.deltaTime * manaDrainSpeed;//魔力消耗
            }
            else
            {
                pState.healing = false;
                anim.SetBool("Heal", false);
                healTimer = 0;
            }
    
            
        }
    
        public float Mana
        {
            get { return mana; }
            set
            {
                if(mana != value)
                {
                    mana = Mathf.Clamp(value, 0, maxMana);
                    manaImage.fillAmount = Mana;
                }
    
            }
        }
    
        void CastSpell()
        {
            if(Input.GetButtonUp("Cast/Heal") && castOrHealtimer <= 0.5f && timeSinceCast >= timeBetweenCast && Mana > manaSpellCost)
            {
                pState.casting = true;
                timeSinceCast = 0;
                StartCoroutine(CastCoroutine());
            }
            else
            {
                timeSinceCast += Time.deltaTime;
            }
            
            if(!Input.GetButton("Cast/Heal"))
            {
                castOrHealtimer = 0;
            }
            
        }
    
        IEnumerator CastCoroutine()
        {
            //橫向技能
            if((yAxis == 0 || (yAxis < 0 && Grounded())) && unlockSideSpell ) //沒有垂直輸入時播放 目前無需要按住上下才能施放的技能
            {
                anim.SetBool("Cast", true);
                yield return new WaitForSeconds(0.1f); //此為等待動畫到達正確播放時間 
    
                GameObject _fireBall = Instantiate(sideSpellFireball, SideAttackTransform.position, Quaternion.identity); //實例化該物件
    
                //Flip火球
                if(pState.lookingRight)
                {
                    _fireBall.transform.eulerAngles = Vector3.zero;
                }
                else
                {
                    _fireBall.transform.eulerAngles = new Vector2(_fireBall.transform.eulerAngles.x, 180); //如果不是面向右邊翻轉180度
                }
                pState.recoilingX = true; //給予玩家反衝
    
                Mana -= manaSpellCost; //魔力減少
                yield return new WaitForSeconds(0.3f); //此為動畫撥放完整時間
            }
    
            anim.SetBool("Cast", false);
            pState.casting = false;
    
        }
    
        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;
            }
        }
        
        void Jump() //跳躍
        {
            //一段跳
            if (jumpBufferCounter > 0 && coyoteTimeCounter > 0 && !pState.jumping)
            {
                
                rb.velocity = new Vector3(rb.velocity.x, jumpForce);
    
                pState.jumping = true;
            }
            //二段跳
            if (!Grounded() && airJumpCounter < maxAirJumps && Input.GetButtonDown("Jump") && unlockAirJump && !isWallSliding)
            {
                
                pState.jumping = true;
    
                airJumpCounter++;
    
                rb.velocity = new Vector3(rb.velocity.x, jumpForce);
            }
            
            if(rb.velocity.y < 0)
            {
                rb.velocity += Vector2.up * Physics2D.gravity.y * (fallMultiplier - 1) * Time.fixedDeltaTime;
    
                pState.jumping = false;
    
            }
            else if(Input.GetButtonUp("Jump") && rb.velocity.y > 0)
            {
                rb.velocity += Vector2.up * Physics2D.gravity.y * (lowJumpMulitiplier - 1) * Time.fixedDeltaTime;
    
                pState.jumping = false;
            }
            
            /*
            if (Input.GetButtonUp("Jump") && rb.velocity.y > 0)
            {
                rb.velocity = new Vector2(rb.velocity.x, 0);
    
                pState.jumping = false;
            }
            */
            anim.SetBool("Jump", !Grounded());
        }
    
        void UpdateJumpVariables()
        {
            if(Grounded())
            {
                pState.jumping = false;
                coyoteTimeCounter = coyoteTime;
                airJumpCounter = 0;  
            }
            else
            {
                coyoteTimeCounter -= Time.deltaTime;
            }
    
            if(Input.GetButtonDown("Jump") )
            {
                jumpBufferCounter = jumpBufferFrames;
            }
            else
            {
                jumpBufferCounter--;
            }
    
        }
    
        private bool Walled()
        {
            return Physics2D.OverlapCircle(wallCheck.position, 0.2f, wallLayer);
        }
    
        void WallSlide()
        {
            if(Walled() && !Grounded() && xAxis !=0)
            {
                isWallSliding = true;
                rb.velocity = new Vector2(rb.velocity.x, Mathf.Clamp(rb.velocity.y, -wallSlidingSpeed, float.MaxValue));
                anim.SetBool("Slide", true);
    
                transform.eulerAngles = new Vector2(transform.eulerAngles.x, 0);
            }
            else
            {
                isWallSliding = false;
                anim.SetBool("Slide", false);
            }
        }
    
        void WallJump()
        {
            if(isWallSliding)
            {
                isWallJumping = false;
                wallJumpingDirection = !pState.lookingRight ? 1 : -1;
    
                CancelInvoke(nameof(StopWallJumping));
            }
    
            if(Input.GetButtonDown("Jump") && isWallSliding)
            {
                anim.SetBool("WallJump", true);
    
                isWallJumping = true;
                rb.velocity = new Vector2(wallJumpingDirection * wallJumpPower.x, wallJumpPower.y);
    
                dashed = false;
                airJumpCounter = 0;
    
                pState.lookingRight = !pState.lookingRight;
                transform.eulerAngles = new Vector2(transform.eulerAngles.x, 180);
    
                Invoke(nameof(StopWallJumping), wallJumpingDuration);
            }
        }
    
        void StopWallJumping()
        {
            anim.SetBool("WallJump", false);
            isWallJumping = false;
            rb.velocity = new Vector2(rb.velocity.x, 0);
            transform.eulerAngles = new Vector2(transform.eulerAngles.x, 0);
        }
    
    }
    

    InventoryManager.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class InventoryManager : MonoBehaviour
    {
        [SerializeField] GameObject fireBall;
        [SerializeField] GameObject dash, airJump, wallJump;
    
        private void OnEnable()
        {
            //能力
            if(PlayerController.Instance.unlockAirJump)
            {
                airJump.SetActive(true);
            }
            else
            {
                airJump.SetActive(false);
            }
    
            if (PlayerController.Instance.unlockDash)
            {
                dash.SetActive(true);
            }
            else
            {
                dash.SetActive(false);
            }
    
            if (PlayerController.Instance.unlockWallJump)
            {
                wallJump.SetActive(true);
            }
            else
            {
                wallJump.SetActive(false);
            }
    
            //技能
            if (PlayerController.Instance.unlockSideSpell)
            {
                fireBall.SetActive(true);
            }
            else
            {
                fireBall.SetActive(false);
            }
        }
    
    }
    
    #15628
    Joseph Tang
    Moderator
    Helpful?
    Up
    0
    ::

    Sorry can you clarify again, what’s the issue here? It seems to function just fine with the first code of using a “switch”.

    #15629
    MI NI
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    My problem is that Inventory’s GetButtonDown did not respond, but GetButton did. After asking ChatGPT, I modified the settings of InputManager and GetButtonDown responded.

    #15632
    Joseph Tang
    Moderator
    Helpful?
    Up
    0
    ::

    However it seems that at the beginning of the video, the GetButtonDown() did function as you opened and closed the inventory.

    #15635
    MI NI
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    At the beginning of the video, the InputManager was correct. To demonstrate, I later changed the InputManager to its original wrong state.

    #15636
    Joseph Tang
    Moderator
    Helpful?
    Up
    0
    ::

    Sorry if I misunderstand but, I don’t see the issue.

    GetButtonDown() will detect your initial press of the button, thus you can use it as a “switch” to turn the inventory on and off.

    Whereas GetButton() will detect the entire duration you hold the button down, thus it’s used to open the inventory only when you are holding the button down. Which i presume was what happened in the latter part of the video

    For your purpose of the “switch” the correct code you are using is fine, and GetButton() would not be used for said purpose.

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: