OnPointerEnter 和 OnPointerExit 未被触发 Unity

OnPointerEnter and OnPointerExit not being triggered Unity

好吧,基本上我一直遇到的问题是,出于某种原因,GameObject 正在干扰 OnPointerEnter 函数。我很确定 OnPointerEnter 只检测到 UI。所以这就是为什么当我看到在这种情况下的特定游戏对象 PlayerLogic 游戏对象(您可以在屏幕截图中看到)出于某种原因干扰 UI 元素的检测时,我感到非常困惑。我相信它是这个特定的 GameObject 的原因是因为一旦我做了 PlayerLogic.SetActive(false); OnPointerEnter 再次开始工作,我也确定它不是 PlayerLogic 的任何子项,因为我已经尝试专门关闭它们但它仍然没有工作。

PlayerLogic 对象的检查器

层次结构

我用来测试 OnPointerEnter 的代码

经过一些测试后,我意识到它的具体问题在于 PlayerLogic GameObject 上的 Player 脚本。现在让我感到困惑的是,一旦我关闭 Player 组件 OnPointer 就不起作用,但是如果我要从 PlayerLogic GameObject OnPointerEnter 作品中完全删除 Player 组件。

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 脚本。

I'm pretty sure that OnPointerEnter detects only UI.

没有

它在 UI 上“开箱即用”,因为默认情况下每个 Canvas 都包含一个 GraphicsRaycaster 组件,然后由 EventSystem 使用和处理。

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

  • 您的对象有 3D Colliders
  • Collider 与 IPointerXY 接口在同一个对象上
  • 在您的 Camera 上有一个 PhysicsRayster 组件

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


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

CharacterController

is simply a capsule shaped Collider which can be told to move in some direction from a script.

这可能阻止了输入。


现在使用您的 Player 代码:

你会

Cursor.lockState = CursorLockMode.Locked;

Awake 中,所以即使您之后将其关闭,这也已经生效。