【发布时间】:2017-12-05 06:09:41
【问题描述】:
我有一个游戏对象列表添加到区域内的列表中,如图所示。我需要的是从原点选择目标的方向输入。我已经得到了这个原点。
我的第一次尝试是通过 rayCast 获得它,但这样做有时需要定向输入直接通过射线击中目标对象。如果输入像案例 #1 那样完成,这没有问题。
但是,我需要它真正起作用的是,当输入方向就像 case #2 或 #3 时,输入仍然会得到一个目标。我的第二次尝试是使用 sphereCast 执行此操作,但它仍然需要一个接近 sphereCast 的目标,并且 sphereCast 击中的多个目标仍然需要通过输入仅导致一个更准确的目标选择。
由于我拥有所有可能目标的所有 transform.position 以及原点,我想有一种更优雅的方法来解决这个问题,即通过比较这些坐标的 vector3(原点和大致方向上的目标)。
这是我的最新方法:
//
// m_targetList is the list containing all GameObjects as GameObjects in other script m_collector. All m_collector does is this.
//
using System.Collections.Generic;
using UnityEngine;
public class TargetSwitcher : MonoBehaviour
{
private TargetCollector m_collector;
private Transform m_origin;
public bool m_targetChanged = false;
public GameObject m_target;
public LayerMask m_targetMask;
private Dictionary<Vector3, float> m_targetInfo = new Dictionary<Vector3, float>();
private void Awake()
{
m_collector = GetComponent<TargetCollector>();
m_origin = GameObject.Find("TargetOrigin").transform;
m_tracker = GameObject.Find("TargetTracker").transform;
m_bound = GetComponent<BoxCollider>();
}
public void UpdateBearing(GameObject origin)
{
m_origin = origin.transform;
foreach (GameObject target in m_collector.m_targetList)
{
Vector3 dir = (target.transform.position - origin.transform.position).normalized
float dist = Vector3.Distance(origin.transform.position, target.transform.position);
m_targetInfo.Add(dir, dist);
}
}
public void SwitchTarget()
{
if (!m_targetChanged)
{
Vector2 dir = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")).normalized;
// Find closest direction value from Dictionary to dir of here
// Compare distance from origin if multiple targets and choose the nearest
}
}
public void ReturnToIdle()
{
m_origin.position = m_target.transform.position;
m_targetChanged = false;
m_targetInfo.Clear();
}
public struct TargetInfo
{
public Vector3 bearing;
public float distance;
public TargetInfo(Vector3 bearing, float distance)
{
this.bearing = bearing;
this.distance = distance;
}
}
}
一般来说,我试图在 SwitchTarget() 之前将方向输入的归一化向量与从原点到每个目标的归一化向量进行比较。这里的输入法是 Gamepad 轴 x 和 y 水平和垂直。
重新发布这个问题,因为提供的答案离问题很远并且被标记为重复(给出的答案是关于仅通过距离查找游戏对象,这个问题是关于方向和距离部分是在找到多个项目时进行二手比较方向)
编辑
在对点积进行了一些试验之后,我确信这很可能是我想要的方向。不过,我需要处理很多不一致的地方。 这是我最近的尝试:
private void Update()
{
UpdateBearing();
Vector3 input = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
if (input != Vector3.zero)
{
SwitchTarget();
}
}
public void UpdateBearing(GameObject origin)
{
m_origin.position = origin.transform.position;
foreach (GameObject target in m_collector.m_targetList)
{
Vector3 dir = (target.transform.position - origin.transform.position).normalized;
if (!m_targetInfo.ContainsKey(target))
{
m_targetInfo.Add(target, dir);
}
}
}
public void SwitchTarget()
{
GameObject oldTarget = m_collector.m_target;
if (!m_targetChanged)
{
Vector3 dir = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0).normalized;
Debug.DrawRay(m_origin.position, dir * 100, Color.yellow, 0.5f);
foreach (KeyValuePair<GameObject, Vector3> possibleTarget in m_targetInfo)
{
float dot = Vector3.Dot(dir, possibleTarget.Value);
if (dot > 0.5f) // Compare DP difference of added dot and input dot
{
GameObject newTarget = possibleTarget.Key;
if (oldTarget != newTarget)
{
Debug.Log(possibleTarget.Value + " // " + dot);
m_target = newTarget;
m_collector.m_target = newTarget;
m_targetChanged = true;
}
}
}
}
}
有了这个,我可以在没有光线投射和丢失任何目标的情况下选择游戏对象。但是,我确信我需要比 if(dot > 0.5f) 更好的案例比较。另外,我粗略的假设是,如果我不为每个键更新字典 m_targetInfo 的值,那么如果这些目标移动了,我就会有另一个不一致的地方。无论如何,我仍然很困惑如何正确地利用它来实现我的最终目标。
【问题讨论】:
标签: unity3d