Input.GetMouseButtonUp 在 Unity 中未按预期工作
Input.GetMouseButtonUp not working as expected in Unity
我有一个 2D Unity 游戏,其中包含许多可以在单击时选择的代理。当这种情况发生时,他们成为玩家(玩家的代理变量被他们替换,代理成为玩家的 parent)。我正在尝试实现一个系统,您可以在其中将他们的目的地拖到另一个代理上以 "Target" 他们。
为了做到这一点,我实际上是从目标的 My class(一个 class 中保存对所有玩家组件和变量的引用)中定位,所以我将代理放入一个函数中由玩家的现任经纪人经营。这在理论上似乎可行,但在 Unity 中,它只允许我定位层次结构中的第一个代理,以及 none 其他代理。但是所有的代理都是代理预制件的相同实例,在游戏开始时生成。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Agent : Grammar {
public Physical physical;
public Agent agent;
void Update() {
float distanceFromMouse = the.Distance(this.transform.position, Camera.main.ScreenToWorldPoint(Input.mousePosition));
if (Input.GetMouseButtonDown(0)) {
if (distanceFromMouse < 1f) {
the.player.agent = this;
the.player.transform.parent = this.transform;
}
}
if (Input.GetMouseButtonUp (0)) {
if (distanceFromMouse < 1f) {
if (the.player.agent != this && the.player.agent is Agent) {
the.player.agent.Target (agent);
}
}
the.player.agent = null;
}
if (the.player.agent == agent)
physical.goal = Camera.main.ScreenToWorldPoint (Input.mousePosition);
else if (physical.hasTarget)
physical.goal = physical.target.transform.position;
}
}
public void Target (My target) {
my.physical.target = target;
my.physical.hasTarget = true;
foreach (My other in the.agents.GetComponentsInChildren<My>()) {
if (other.physical.targetters.Contains (my))
other.physical.targetters.Remove (my);
}
target.physical.targetters.Add (my);
target.physical.targetted = true;
}
这是我的语法 class,一切都继承自它,因此它们可以访问全局 class。
using UnityEngine;
using System.Collections;
public class Grammar : MonoBehaviour {
public A a;
public The the;
}
这是我的(全局实用程序)class
using UnityEngine;
using System.Collections;
public class The : MonoBehaviour {
public Grid grid;
public GameObject world;
public Player player;
public GameObject squareParent;
public GameObject linkParent;
public GameObject nodeParent;
public GameObject agents;
public Vector2 HeadingFrom(float angle) { return new Vector2(Mathf.Cos(angle * Mathf.Deg2Rad), Mathf.Sin(angle * Mathf.Deg2Rad)); }
public float AngleFrom(Vector2 heading) { return Mathf.Atan2 (heading.y, heading.x) * Mathf.Rad2Deg; }
public Vector2 RelativeHeadingFrom(Vector2 heading, float rotation) { return (Vector2)(HeadingFrom(AngleFrom(heading) - rotation)); }
public float Distance(Vector2 from, Vector2 to) { return (Heading(from,to)).magnitude; }
public Vector2 Heading (Vector2 from, Vector2 to) { return to - from; }
public Vector2 MidPoint (GameObject my, GameObject their) { return (my.transform.position + their.transform.position) / 2; }
}
您在代理 class 中检测点击的方式有点不对。而 属性 Input.mousePosition
returns 一个 Vector3 的 Z 分量始终为零。 Camera.ScreenToWorldPoint
函数的 documentation 注意到所提供向量的 Z 分量是距离相机的世界单位距离,这意味着你的 "clicks" 在特工 class 将永远在摄像机旁边。
通常的方法是定义 OnMouseDown() 和 OnMouseUp() 方法(在您的 Agent class 中)或使用 Camera.ScreenPointToRay
创建一个 Ray,然后用于进行光线投射进入场景,然后使用光线命中结果作为鼠标指针的 'actual world' 位置。有关详细信息,请参阅 Unity Answers 上的 answer。
我建议您使用新的事件系统(它是新的 Unity GUI 系统的一部分)来检测是否已单击代理,因为如果您希望游戏在移动设备。
您需要做的是:
- 在您的代理中实现接口 IPointerUpHandler and IPointerDownHandler class 并在接口要求您定义的方法中处理点击。
- 确保你的代理上有某种碰撞器(或触发器)。
- 确保在相机对象上添加 PhysicsRaycaster 组件。
您可能还对这些界面感兴趣:
我有一个 2D Unity 游戏,其中包含许多可以在单击时选择的代理。当这种情况发生时,他们成为玩家(玩家的代理变量被他们替换,代理成为玩家的 parent)。我正在尝试实现一个系统,您可以在其中将他们的目的地拖到另一个代理上以 "Target" 他们。
为了做到这一点,我实际上是从目标的 My class(一个 class 中保存对所有玩家组件和变量的引用)中定位,所以我将代理放入一个函数中由玩家的现任经纪人经营。这在理论上似乎可行,但在 Unity 中,它只允许我定位层次结构中的第一个代理,以及 none 其他代理。但是所有的代理都是代理预制件的相同实例,在游戏开始时生成。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Agent : Grammar {
public Physical physical;
public Agent agent;
void Update() {
float distanceFromMouse = the.Distance(this.transform.position, Camera.main.ScreenToWorldPoint(Input.mousePosition));
if (Input.GetMouseButtonDown(0)) {
if (distanceFromMouse < 1f) {
the.player.agent = this;
the.player.transform.parent = this.transform;
}
}
if (Input.GetMouseButtonUp (0)) {
if (distanceFromMouse < 1f) {
if (the.player.agent != this && the.player.agent is Agent) {
the.player.agent.Target (agent);
}
}
the.player.agent = null;
}
if (the.player.agent == agent)
physical.goal = Camera.main.ScreenToWorldPoint (Input.mousePosition);
else if (physical.hasTarget)
physical.goal = physical.target.transform.position;
}
}
public void Target (My target) {
my.physical.target = target;
my.physical.hasTarget = true;
foreach (My other in the.agents.GetComponentsInChildren<My>()) {
if (other.physical.targetters.Contains (my))
other.physical.targetters.Remove (my);
}
target.physical.targetters.Add (my);
target.physical.targetted = true;
}
这是我的语法 class,一切都继承自它,因此它们可以访问全局 class。
using UnityEngine;
using System.Collections;
public class Grammar : MonoBehaviour {
public A a;
public The the;
}
这是我的(全局实用程序)class
using UnityEngine;
using System.Collections;
public class The : MonoBehaviour {
public Grid grid;
public GameObject world;
public Player player;
public GameObject squareParent;
public GameObject linkParent;
public GameObject nodeParent;
public GameObject agents;
public Vector2 HeadingFrom(float angle) { return new Vector2(Mathf.Cos(angle * Mathf.Deg2Rad), Mathf.Sin(angle * Mathf.Deg2Rad)); }
public float AngleFrom(Vector2 heading) { return Mathf.Atan2 (heading.y, heading.x) * Mathf.Rad2Deg; }
public Vector2 RelativeHeadingFrom(Vector2 heading, float rotation) { return (Vector2)(HeadingFrom(AngleFrom(heading) - rotation)); }
public float Distance(Vector2 from, Vector2 to) { return (Heading(from,to)).magnitude; }
public Vector2 Heading (Vector2 from, Vector2 to) { return to - from; }
public Vector2 MidPoint (GameObject my, GameObject their) { return (my.transform.position + their.transform.position) / 2; }
}
您在代理 class 中检测点击的方式有点不对。而 属性 Input.mousePosition
returns 一个 Vector3 的 Z 分量始终为零。 Camera.ScreenToWorldPoint
函数的 documentation 注意到所提供向量的 Z 分量是距离相机的世界单位距离,这意味着你的 "clicks" 在特工 class 将永远在摄像机旁边。
通常的方法是定义 OnMouseDown() 和 OnMouseUp() 方法(在您的 Agent class 中)或使用 Camera.ScreenPointToRay
创建一个 Ray,然后用于进行光线投射进入场景,然后使用光线命中结果作为鼠标指针的 'actual world' 位置。有关详细信息,请参阅 Unity Answers 上的 answer。
我建议您使用新的事件系统(它是新的 Unity GUI 系统的一部分)来检测是否已单击代理,因为如果您希望游戏在移动设备。
您需要做的是:
- 在您的代理中实现接口 IPointerUpHandler and IPointerDownHandler class 并在接口要求您定义的方法中处理点击。
- 确保你的代理上有某种碰撞器(或触发器)。
- 确保在相机对象上添加 PhysicsRaycaster 组件。
您可能还对这些界面感兴趣: