OnPointerEnter 和 OnPointerExit 没有被触发 Unity

Posted

技术标签:

【中文标题】OnPointerEnter 和 OnPointerExit 没有被触发 Unity【英文标题】:OnPointerEnter and OnPointerExit not being triggered Unity 【发布时间】:2022-01-14 00:27:50 【问题描述】:

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

PlayerLogic 对象的检查器

层次结构

我用来测试 OnPointerEnter 的代码

经过一些测试,我意识到它的具体问题在于 PlayerLogic GameObject 上的 Player 脚本。现在让我感到困惑的是,一旦我关闭了 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 脚本。

【问题讨论】:

【参考方案1】:

我很确定 OnPointerEnter 只检测 UI。

没有。

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

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

你的对象有3D Colliders 碰撞器与IPointerXY 接口位于同一对象上 在您的Camera 上有一个PhysicsRayster 组件

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

你的对象有一个2D Collider 碰撞器与IPointerXY 接口位于同一对象上 Camera 有一个Physics2DRaycaster 组件

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

CharacterController

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

这可能会阻塞输入。


现在使用您的Player 代码:

你会的

Cursor.lockState = CursorLockMode.Locked;

Awake 所以即使你之后关闭它也已经生效。

【讨论】:

好吧,我的相机上既没有 PhysicsRaycaster 也没有 Physics2DRaycaster。所以我仍然对 PlayerLogic 对象可能与 OnPointerEnter 函数有什么关系感到困惑? @user12791203 我认为CharacterController 可能会干扰.. CharacterController 基本上 一个碰撞器所以它可能以某种方式妨碍...对于@987654343 @我没有任何代码或参考 您的Player 脚本是否可能以某种方式启用和禁用CharacterController 嗯...我不认为 CharacterController 会产生干扰,因为一旦我让它处于非活动状态 OnPointerEnter 仍然无法工作。我不认为这是 Player 中的代码,因为当我将 Player 设置为非活动 OnPointerEnter 时仍然不起作用。当我从 PlayerLogic 对象中完全删除 Player 时,它开始工作。该脚本不会以任何方式禁用或启用角色控制器,我会将其添加到问题中以便您查看。 @user12791203 但您的 Player 组件锁定并隐藏了光标..这可能是问题吗? (不明白为什么我们都被否决了……但遗憾的是,*** 上有一些“欢迎”的人)

以上是关于OnPointerEnter 和 OnPointerExit 没有被触发 Unity的主要内容,如果未能解决你的问题,请参考以下文章

unity ui中使用onmouseover

unityguilayout的button怎么判定按住状态

& 和 && 区别和联系,| 和 || 区别和联系

第三十一节:扫盲并发和并行同步和异步进程和线程阻塞和非阻塞响应和吞吐等

shell中$()和 ` `${}${!}${#}$[] 和$(()),[ ] 和(( ))和 [[ ]]

Java基础8---面向对象代码块和继承和this和super和重写和重载和final