OnPointerEnter 和 OnPointerExit 没有被触发 Unity

问题描述 投票:0回答:1

好吧,基本上我遇到的问题是,由于某种原因,GameObject 干扰了 OnPointerEnter 函数。我很确定 OnPointerEnter 只检测 UI。因此,当我看到本例中的特定 GameObject(即 PlayerLogic GameObject)(您可以在屏幕截图中看到)由于某种原因干扰 UI 元素的检测时,我感到非常困惑。我之所以相信它是这个特定的 GameObject 是因为一旦我执行了 PlayerLogic.SetActive(false); OnPointerEnter 再次开始工作,而且我也确信它不是 PlayerLogic 的任何子项,因为我已经尝试专门关闭它们,但它仍然不起作用。

PlayerLogic 对象的检查器

层次结构

我用来测试 OnPointerEnter 的代码

经过一些测试,我意识到具体问题出在 PlayerLogic 游戏对象上的玩家脚本中。现在让我困惑的是,一旦我关闭 Player 组件 OnPointer 就不起作用,但如果我从 PlayerLogic GameObject 中完全删除 Player 组件,OnPointerEnter 就可以工作。

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using System.Collections.Generic;

public class Player : MonoBehaviour, TakeDamage {

    [SerializeField] private Animator playerAnimator;

    [SerializeField] private Transform mainCameraTransform;
    private bool isRunning = false; 

    [SerializeField] private CharacterController controller;
    public float speed = 10f;
    [SerializeField] private float jumpForce = 3f;
    [SerializeField] private float gravity = -10000.81f;
    Vector3 velocity;
    Vector3 desiredMoveDirection;

    private float dashSpeed = 30f;

    private float mouseX;
    private float mouseY;
    [SerializeField]
    private Transform Target;
    [SerializeField]
    private Transform player;
    
    private float turnSmoothVelocity;    

    private float time = 0f;
    public bool playerIsAttacking = false;

    [SerializeField] private Slider playerHealth, playerMana;
    [SerializeField] private TextMeshProUGUI healthText, manaText; 

    private Vector3 originalSpawnPos;
    private bool playerIsDead = false;

    [SerializeField] private LayerMask enemyLayerMask;
    [SerializeField] private Transform playerLook;

    private ShowHPBar obj;
    private bool HPBarShown = false;
    private bool unshowingHPBar = false;
    public bool lookingAtEnemy = false;
    public RaycastHit hit;

    [SerializeField] private Canvas abilityCanvas;
    [SerializeField] private Slider CD1;
    [SerializeField] private Slider CD2;
    [SerializeField] private Slider CD3;
    public List<Ability> currentlyEquippedAbilites = new List<Ability>();
    public List<string> abilityTexts = new List<string>();
    public float[] abilityCooldowns = new float[3]; 
    private float manaRegenTime;
    //public List<Image> abilityImages = new List<Image>();

    private void Awake() {
        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Locked;
    }

    private void Start() {
        playerHealth.onValueChanged.AddListener(delegate {OnValueChangedHealth(); });
        playerMana.onValueChanged.AddListener(delegate {OnValueChangedMana(); });
        originalSpawnPos = transform.position;
    }

    private void Update() {
        if (!playerIsDead) {
            PlayerMovementAndRotation();
        }
        PlayerDash();
        PlayerRun();
        PlayerSeeEnemyHealth();
        PlayerActivateAbility();

        if (manaRegenTime > 0.5f) {
            playerMana.value += playerMana.maxValue/100; 
            manaRegenTime = 0;
        }
        playerLook.rotation = mainCameraTransform.rotation;
        time += Time.deltaTime;
        manaRegenTime += Time.deltaTime;

        #region Ability Cooldowns
        if (currentlyEquippedAbilites.Count > 0) {
            if (currentlyEquippedAbilites[0].cooldown <= abilityCooldowns[0])
            {
                currentlyEquippedAbilites[0].isOnCooldown = false;
                abilityCooldowns[0] = 0;
                CD1.value = 0;
            }
            else if (currentlyEquippedAbilites[0].isOnCooldown) { 
                abilityCooldowns[0] += Time.deltaTime; 
                CD1.value = currentlyEquippedAbilites[0].cooldown - abilityCooldowns[0];
            }
        }

        if (currentlyEquippedAbilites.Count > 1) {
            if (currentlyEquippedAbilites[1].cooldown <= abilityCooldowns[1])
            {
                currentlyEquippedAbilites[1].isOnCooldown = false;
                abilityCooldowns[1] = 0;
                CD2.value = 0;
            }
            else if (currentlyEquippedAbilites[1].isOnCooldown) { 
                abilityCooldowns[1] += Time.deltaTime; 
                CD2.value = currentlyEquippedAbilites[1].cooldown - abilityCooldowns[1];
            }
        }

        if (currentlyEquippedAbilites.Count > 2) {
            if (currentlyEquippedAbilites[2].cooldown <= abilityCooldowns[2])
            {
                currentlyEquippedAbilites[2].isOnCooldown = false;
                abilityCooldowns[2] = 0;
                CD3.value = 0;
            }
            else if (currentlyEquippedAbilites[2].isOnCooldown) { 
                abilityCooldowns[2] += Time.deltaTime; 
                CD3.value = currentlyEquippedAbilites[2].cooldown - abilityCooldowns[2];
            }
        }
        #endregion
    }

    private void PlayerRun() {
        if (Input.GetKey(KeybindsScript.RunKey) && (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)) {
            playerAnimator.SetInteger("isRunning", 1);
            playerAnimator.SetInteger("isIdle", 0);
            playerAnimator.SetInteger("isWalking", 0);
            speed = 15f;
        }
        else if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0) {
            playerAnimator.SetInteger("isWalking", 1);
            playerAnimator.SetInteger("isIdle", 0);
            playerAnimator.SetInteger("isRunning", 0);
            speed = 10f;
        }
        else {
            playerAnimator.SetInteger("isRunning", 0);
            playerAnimator.SetInteger("isWalking", 0);
            playerAnimator.SetInteger("isIdle", 1);
            speed = 10f;
        }
    }

    private void PlayerMovementAndRotation() {
        bool isGrounded = controller.isGrounded;

        if (isGrounded && velocity.y < 0) {
            velocity.y = -2f;
        }
        float horizontal = Input.GetAxisRaw("Horizontal");
        float vertical = Input.GetAxisRaw("Vertical");
        Vector3 moveDir = (transform.right*horizontal+transform.forward*vertical).normalized;

        controller.Move(moveDir*Time.deltaTime*speed);
        transform.eulerAngles = new Vector3(0f, mainCameraTransform.eulerAngles.y, 0f);
        

        if (Input.GetKeyDown(KeybindsScript.JumpKey) && isGrounded) {
            velocity.y = Mathf.Sqrt(jumpForce * -2f * gravity);
        }

        velocity.y += gravity * Time.deltaTime;

        controller.Move(velocity * Time.deltaTime);
    }

    private void PlayerDash() {
        if (Input.GetKeyDown(KeybindsScript.DashKeybind) && isRunning == false) {
            if (Input.GetKey(KeybindsScript.MovementKeyBackward)) {
                StartCoroutine(PlayerDashTiming(2));
            }
            else if (Input.GetKey(KeybindsScript.MovementKeyRight)) {
                StartCoroutine(PlayerDashTiming(3));
            }
            else if (Input.GetKey(KeybindsScript.MovementKeyLeft)) {
                StartCoroutine(PlayerDashTiming(4));
            }
            else {
                StartCoroutine(PlayerDashTiming(1));
            }
        }
    }

    private void PlayerSeeEnemyHealth() {
        if (Physics.Raycast(playerLook.position, playerLook.forward, out hit, 1000f, enemyLayerMask)) {
            obj = hit.transform.gameObject.GetComponent<ShowHPBar>();
            if (obj != null && !HPBarShown && !unshowingHPBar) {obj.ShowHPBarFunction(); HPBarShown = true;}
            lookingAtEnemy = true;
        }
        else {
            if (obj != null && HPBarShown) {StartCoroutine(UnShowHPBar(obj)); HPBarShown = false;}
        }
    }

    public void PlayerEquipAbility(Ability ability, int place) {
        if (currentlyEquippedAbilites.Count < place) {currentlyEquippedAbilites.Add(ability);}
        else {currentlyEquippedAbilites[place-1] = ability;}

        //if (abilityImages.Count < place) {abilityImages.Add(ability.icon);}
        //else {abilityImages.Add(ability.icon);}
        if (abilityTexts.Count < place) {abilityTexts.Add(ability.name);}
        else {abilityTexts[place-1] = ability.name;}
        for (int i=0;i < abilityTexts.Count;++i) {
            abilityCanvas.transform.GetChild(i).GetChild(0).GetComponent<TextMeshProUGUI>().text = abilityTexts[i];
            abilityCanvas.transform.GetChild(i).GetChild(1).GetComponent<Slider>().maxValue = ability.cooldown;
        }
    }

    private void PlayerActivateAbility() { 
        if (Input.GetKeyDown(KeyCode.Alpha1)) {
            if (currentlyEquippedAbilites[0] != null) {
                if (currentlyEquippedAbilites[0].manaCost <= playerMana.value && !currentlyEquippedAbilites[0].isOnCooldown) {
                    ParticleEffect pe = currentlyEquippedAbilites[0].script.gameObject.GetComponent<ParticleEffect>();
                    playerMana.value -= currentlyEquippedAbilites[0].manaCost;
                    currentlyEquippedAbilites[0].isOnCooldown = true;
                    if (pe != null) {pe.PlayAnimation();}
                }
            }
        }
    }


    public void OnValueChangedHealth() {
        healthText.text = playerHealth.value + "/" + PlayerStats.HealthPoints;
    }

    public void OnValueChangedMana() {
        manaText.text = playerMana.value + "/" + PlayerStats.ManaAmount;
    }

    public void TakeDamageFunction(float damage) {
        playerHealth.value -= damage;
        if (playerHealth.value <= 0) {
            StartCoroutine(PlayerDeath());
        }
    }


    IEnumerator PlayerDashTiming(int x) {
        isRunning = true;
        float time = 0f;
        Vector3 savedVector = Vector3.zero;
        switch (x) {
            case 1: 
            savedVector = transform.forward;
            break;
            case 2:
            savedVector = -transform.forward;
            break;
            case 3:
            savedVector = transform.right;
            break;
            case 4:
            savedVector = -transform.right;
            break;
        }
        while(time < .3f)
        {
            time += Time.deltaTime;
            controller.Move(savedVector * dashSpeed * Time.deltaTime);
            yield return null; 
        }
        yield return new WaitForSeconds(1.5f);
        isRunning = false;
    }

    IEnumerator PlayerDeath() {
        //Respawn
        playerIsDead = true;
        playerAnimator.enabled = false;
        yield return new WaitForSeconds(1f);
        playerHealth.value = 100;
        transform.position = originalSpawnPos;
        yield return new WaitForSeconds(0.1f);
        playerIsDead = false;
        playerAnimator.enabled = true;
    }

    IEnumerator UnShowHPBar(ShowHPBar obj) {
        unshowingHPBar = true;
        yield return new WaitForSeconds(1.5f);
        obj.ShowHPBarFunction();
        unshowingHPBar = false;
    }
}

这是 Player.cs 脚本。

c# unity-game-engine raycasting
1个回答
3
投票

我很确定 OnPointerEnter 只检测 UI。

没有。

它在 UI 上“开箱即用”,因为默认情况下每个

Canvas
都包含一个
GraphicsRaycaster
组件,然后由
EventSystem
使用和处理。

对于非 UI 3D 对象,您必须确保

对于非 UI 2D 对象非常相似


请注意,任何其他对撞机或一般光线投射阻挡对象可能位于您的输入和目标对象之间,这也会阻止在您的对象上触发

OnPointerXY

CharacterController

只是一个胶囊形碰撞器 可以告诉它从脚本向某个方向移动。

这可能会阻塞输入。


现在输入您的

Player
代码:

你愿意

Cursor.lockState = CursorLockMode.Locked;

Awake
所以即使你事后将其关闭它也已经生效了。

© www.soinside.com 2019 - 2024. All rights reserved.