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的主要内容,如果未能解决你的问题,请参考以下文章
第三十一节:扫盲并发和并行同步和异步进程和线程阻塞和非阻塞响应和吞吐等