【发布时间】:2019-05-27 19:17:16
【问题描述】:
在这种情况下我有两个主要问题:
NAVI 是播放器 (FPSController) 的子级,因此 NAVI 与播放器一起移动。但是 NAVI 也位于玩家前面一点,结果是光线投射一直是第一次击中 NAVI 而不是击中 Interactable 对象。
如果玩家和一些可交互对象之间有一扇门,它会检测到该对象。但是如果玩家和可交互对象之间有一扇门和其他对象,它不应该检测到它们。玩家看不到它们,但它正在检测。
此脚本附加到 plaher (FPSController):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DetectInteractable : UnityEngine.MonoBehaviour
{
public Camera cam;
public float distanceToSee;
public string objectHit;
public bool interactableObject = false;
public Transform parentToSearch;
public Scaling scaling;
public int spinX = 0;
public int spinY = 0;
public int spinZ = 0;
public GameObject navi;
public GameObject itemsDescriptionCanvas;
public Text itemsDescriptionText;
private RaycastHit whatObjectHit;
private Transform[] childrenToSearhc;
private void Start()
{
childrenToSearhc = parentToSearch.GetComponentsInChildren<Transform>();
}
private void Update()
{
if (cam.enabled == true)
{
if (Input.GetMouseButtonDown(0) && !scaling.scaleUp)
{
if (whatObjectHit.collider != null)
ExecuteActions(whatObjectHit.collider.gameObject);
}
Debug.DrawRay(cam.transform.position, cam.transform.forward * distanceToSee, Color.magenta);
if (Physics.Raycast(cam.transform.position, cam.transform.forward, out whatObjectHit, distanceToSee))
{
objectHit = whatObjectHit.collider.gameObject.name;
interactableObject = true;
print("Hit ! " + whatObjectHit.collider.gameObject.name);
if (scaling.objectToScale.transform.localScale == scaling.minSize)
{
scaling.objectToScale.transform.Rotate(spinX, spinY, spinZ);
}
ProcessItemsDescripations();
itemsDescriptionCanvas.SetActive(true);
}
else
{
if (scaling.objectToScale.transform.localScale == scaling.minSize)
{
navi.transform.rotation = new Quaternion(0, 0, 0, 0);
}
itemsDescriptionCanvas.SetActive(false);
print("Not Hit !");
}
}
}
private void ExecuteActions(GameObject go)
{
var ia = go.GetComponent<ItemAction>();
if (ia != null)
{
ia.ItemMove();
}
}
void ProcessItemsDescripations()
{
foreach (Transform child in childrenToSearhc)
{
if (child.GetComponent<ItemInformation>() != null)
{
ItemInformation iteminformation = child.GetComponent<ItemInformation>();
if (child.name == objectHit)
{
itemsDescriptionText.text = iteminformation.description;
}
}
}
}
public class ViewableObject : UnityEngine.MonoBehaviour
{
public string displayText;
public bool isInteractable;
}
}
这个小脚本附加到每个 Interactable 对象:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemInformation : UnityEngine.MonoBehaviour
{
[TextArea]
public string description;
}
这是播放器(FPSController)Inspector设置的截图:
此屏幕截图是作为播放器子级的 NAVI: 您可以在左侧的游戏窗口和场景窗口看到 NAVI:
这是窗口的屏幕截图示例。窗口应该是 Interactable 对象并且应该被光线投射检测到:
窗口标签设置为无标签,图层设置为默认
这是游戏运行时的屏幕截图,玩家站在门后,门的另一侧有一个带有可交互窗口的房间。没有什么能阻止光线投射穿过门并检测到窗户。这不是逻辑。玩家看不到窗口。所以不应该检测到窗口:
在左上角,光线投射的洋红色穿过门到达窗户。在左下角,玩家站在门后,完全可以看到窗户,但它正在检测窗户:
但是当使用断点时,你可以看到真正被击中的是 NAVI,而不是门而不是窗户,而是 NAVI,因为 NAVI 总是站在玩家面前:
在此之前,我尝试在脚本中使用光线投射遮罩层,然后将窗口层更改为可交互,然后我看到它正在通过门进行检测。
最后的主要目标是:
为了检测游戏中的可交互对象而不是检测 NAVI,他不是可交互对象,所以以某种方式使 NAVI 不会阻挡光线投射!
并且只有在玩家对对象有逻辑视图时才能检测到对象。并且不检测来自门后或墙壁或其他物体的物体。
【问题讨论】:
-
Physics.Raycast 允许您传递它应该忽略的图层蒙版 (docs.unity3d.com/ScriptReference/Physics.Raycast.html),该链接还显示了如何使光线投射命中除应有帮助的特定图层之外的所有内容。
-
只是出于好奇,您是否在使用某种预制资产?因为我向上帝发誓,我已经看到至少 3 个不同的 SO 帐户使用几乎相同的图片发布,这些图片看起来像是同一个项目。 No really.
-
@Draco18s 不,我猜是我在 * 的另一个帐户中
-
@yochile 你应该把它们合并,然后。真的没有理由不这样做。