Unity,改变子对象的旋转。无法访问子对象
Posted
技术标签:
【中文标题】Unity,改变子对象的旋转。无法访问子对象【英文标题】:Unity, Changing the rotation of a child object. Cannot access the child object 【发布时间】:2015-09-22 15:34:27 【问题描述】:我正在设计 2D 游戏中玩家瞄准和射击的逻辑。当用户在屏幕上单击并拖动时,它应该围绕精灵旋转一条由 3 个点组成的线,与玩家拖动的角度相同,以便他可以瞄准。就像在泡泡射击游戏中一样。
“Player”预制件有一个名为“Sight”的子对象,它是一个将 4 个点精灵作为具有相应偏移量的子对象的变换,因此旋转“Sight”将旋转整条线。
在我查看的每个更新循环中,视线根据鼠标位置旋转,但变量视线似乎为空。我试图通过标签获取对象,并拥有一个公共变量,这样我就可以从检查器中分配预制件。我也试图只抓住变换组件。我确信这是一个非常愚蠢的问题,但我看不到它。我将不胜感激。
瞄准逻辑:
public class PlayerShooting : MonoBehaviour
public GameObject BulletPrefab;
public float coolDownTimer = 0.0f;
public float aimDistance = 0.5f;
private Vector2 originPoint = new Vector2 (0f,0f);
private Vector2 endPoint = new Vector2(0f,0f);
private bool dragging = false;
public GameObject sight;
// Update is called once per frame
void Update ()
// TOUCH DOWN
if (Input.GetMouseButtonDown(0) == true)
originPoint = getPointInWorld(Input.mousePosition);
endPoint = originPoint;
dragging = true;
// TOUCH UP
if (Input.GetMouseButtonUp(0) == true)
endPoint = getPointInWorld(Input.mousePosition);
dragging = false;
FireBullet();
// DRAGGING
if (dragging)
endPoint = getPointInWorld(Input.mousePosition);
// AIM
// !!!: THIS IS THE ISSUE
sight = GameObject.Find("Player/Sight");
if (sight != null && endPoint != originPoint)
Vector2 dir = originPoint - endPoint;
dir.Normalize();
float zAngle = Mathf.Atan2 (dir.y,dir.x) * Mathf.Rad2Deg - 90;
Quaternion newRotation = Quaternion.Euler(0,0,zAngle);
sight.transform.rotation = newRotation;
else
Debug.Log("Error: cannot aim because Sight was not instantiated");
void FireBullet ()
Vector2 getPointInWorld (Vector3 point)
Vector2 pos = Camera.main.ScreenToWorldPoint(point);
return pos;
【问题讨论】:
有关游戏引擎的问题,请使用unity3d
标签而不是unity
。
下次我会注意的,谢谢。
注意:我知道当 originPont 和 endPoint 相等时会出现错误。我更改了 if 语句并确认视线始终为空。
【参考方案1】:
好的,您的脚本中有多个不推荐的做法。正如您所说,您应该更喜欢 FindObjectWithTag,甚至更好的是通过检查器分配它。为此,请执行以下操作:创建一个名为 visionReference 的公共变量(或具有 [Serializable] 属性的私有变量)。然后保存你的脚本。将它附加到您的播放器后,将“Sight”拖到您的检查器脚本中的SightReference(选择播放器对象后,如果您已展开脚本,您应该会看到一个空白字段);目前,它在您发布的图片中显示为无(游戏对象),将视线拖到那里。
另外,为了检测拖动,你应该使用事件,而不是通过 Input 推断它。如果您想要关于事件的精彩教程,watch this one(您可以从头开始观看,但您需要的内容大约从那个时候开始)。要么实现接口(我建议这样做,即使一开始看起来很容易也很容易),或者统一使用事件触发组件。
旧答案:
好的,假设您希望线条始终为 3 个点。我要做的是创建一个由 3 个点组成的精灵。这样,它只是一个对象(你可以用 3 个单独的精灵来做,但它可能会变得更复杂,所以为了简单起见,我将采用这个假设 - 你可以稍后更改它)。
确保瞄准线精灵的轴心点位于精灵的底部中间(您可以在线查找,设置轴心在精灵编辑器中)。您也可以将其留在中间,并在底部中间创建一个父对象,并将其用作枢轴,但现在还是简单的。
现在您有了一个带有该精灵的对象,该对象围绕其底部中间的枢轴点旋转,因此它的工作原理类似于时钟指针。尝试更改检查器中的旋转以验证这一点。
现在,让这条瞄准线的父级成为玩家,让它跟随玩家。调整其位置,使其不与播放器重叠。
现在,编写一个脚本并将其附加到瞄准线上。在 C# 中:
void Update()
Vector3 mouseWorldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 lineWorldPosition = this.transform.parent.position;
Vector3 lookAtVector = mouseWorldPosition - lineWorldPosition;
float angle = Mathf.Atan2(lookAtVector.x, lookAtVector.y) * Mathf.Rad2Deg;
this.transform.localRotation = Quaternion.Euler(0, 0, -angle);
这假设在旋转 0,0,0 时瞄准线与 Y 轴对齐(它指向上方)。
【讨论】:
我不能使用事件方法,因为可拖动区域是全屏。如果我想检测被拖动的视线,事件会很好。这是一个有趣的教程,+1。【参考方案2】:退后一步后,似乎没有对象可以分配给变量视线,因为场景文件已损坏。它是从 Bitbucket 存储库中克隆的。原来的方法工作正常和指令
sight = GameObject.Find("Player/Sight");
能够找到对象。我决定从脚本而不是从编辑器中分配它,这样我就可以在玩家正在射击时启用和禁用瞄准器。
【讨论】:
以上是关于Unity,改变子对象的旋转。无法访问子对象的主要内容,如果未能解决你的问题,请参考以下文章
WPF中的TreeView,如何改变子节点的顺序, 给个例子,多谢
unity细节基于unity子对象(如相机)为什么无法进行z轴的拖拽移动和z轴自动归位的问题