C# 如何使“看不见的墙”脚本工作并生效?

C# 如何使“看不见的墙”脚本工作并生效?,c#,unity3d,C#,Unity3d,这样做的目的是,当玩家走到地形边缘时,他将无法继续行走并摔倒 在我的例子中,我希望物体在与不可见的墙碰撞时向前移动,物体会把lerp转回来,移动到不可见墙的另一边 我后来读到的另一个问题是,如果物体移动到看不见的墙壁上的速度过快,就会有一个bug让它们通过?我不确定 这是一张显示隐形墙的屏幕截图。我创建了一个长方体碰撞器,将触发器设置为打开,并将500设置为与地形大小相同的大小 这是不可见墙的脚本:我将其附加到地形的脚本: using UnityEngine; using System.Col

这样做的目的是,当玩家走到地形边缘时,他将无法继续行走并摔倒

在我的例子中,我希望物体在与不可见的墙碰撞时向前移动,物体会把lerp转回来,移动到不可见墙的另一边

我后来读到的另一个问题是,如果物体移动到看不见的墙壁上的速度过快,就会有一个bug让它们通过?我不确定

这是一张显示隐形墙的屏幕截图。我创建了一个长方体碰撞器,将触发器设置为打开,并将500设置为与地形大小相同的大小

这是不可见墙的脚本:我将其附加到地形的脚本:

using UnityEngine;
using System.Collections;

public class InvisibleWalls : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }

    void OnTriggerExit(Collider other)
    {

    }
}
这是创建太空船的脚本,它克隆了太空船,并使太空船前进。但当他们到达地形边缘时,他们就出去了。我希望他们回到另一边

此脚本附加到球体游戏对象:

在启动函数中,我添加了:

private void Start()
    {
        spheres = GameObject.FindGameObjectsWithTag("MySphere");

        var withTag = GameObject.FindWithTag("Terrain");
        if (withTag == null)
            throw new InvalidOperationException("Terrain not found");

        boundLower = terrain.transform.position - terrain.transform.size / 2;
        boundUpper = terrain.transform.position + terrain.transform.size / 2;
    }
但在两行上都出现错误:size属性不存在:

boundLower = terrain.transform.position - terrain.transform.size / 2;
boundUpper = terrain.transform.position + terrain.transform.size / 2;
并将MoveShips功能更改为:

private Vector3 direction = Vector3.forward;
    private void MoveShips() {
        foreach (var child in spheres) {
            var pos = child.transform.position + direction * Time.deltaTime * moveSpeed;
            pos.x = Mathf.Clamp(pos.x, boundLower.x, boundUpper.x);
            pos.z = Mathf.Clamp(pos.z, boundLower.z, boundUpper.z);
            if (pos.x == boundLower.x || pos.x == boundUpper.x) direction.x = - direction.x;
            if (pos.z == boundLower.z || pos.z == boundUpper.z) direction.z = - direction.z;
            child.transform.position = pos;
        }
    }

我建议修改
MoveShips()

private Vector3 direction = Vector3.forward;
private void MoveShips() {
    foreach (var child in spheres) {
        var pos = child.transform.position + direction * Time.deltaTime * moveSpeed;
        pos.x = Mathf.Clamp(pos.x, boundLower.x, boundUpper.x);
        pos.z = Mathf.Clamp(pos.z, boundLower.z, boundUpper.z);
        if (pos.x == boundLower.x || pos.x == boundUpper.x) direction.x = - direction.x;
        if (pos.z == boundLower.z || pos.z == boundUpper.z) direction.z = - direction.z;
        child.transform.position = pos;
    }
}
对于这样一件简单的事情,这将消除对对象碰撞引擎不必要的依赖。请注意,这是如何使所有船舶在最远到达边界时改变方向的。如果希望它们单独移动,则需要将此逻辑移动到单独的脚本,并将其附加到船舶预制件

边界(
boundLower
boundUpper
)可以在编辑器中设置为脚本变量,也可以从地形计算,如:

boundLower = terrain.transform.position - terrain.TerrainData.size / 2;
boundUpper = terrain.transform.position + terrain.TerrainData.size / 2;
我还建议采取以下行动:

var withTag = GameObject.FindWithTag("Terrain");
if (withTag == null)
    throw new InvalidOperationException("Terrain not found");

Update()

问题:物体不会碰撞,为什么?

答:对象不会从碰撞器中的碰撞,只能从外部碰撞

在你的例子中,你需要的是4个盒子的对撞机,在地图的每一个边缘都有一个

问题:我后来读到的另一个问题是,如果物体移动到看不见的墙上太快,就会有一个bug让它们通过?不确定。

这只是物体以类似子弹的速度移动的问题,您可以编辑刚体,使其具有检测模式:“连续”或“连续动态”,这将避免此问题


脚本,我不认为在这种情况下你会需要它们,你最初的想法是好的,只是在整个地形上实现一个碰撞器,而不是4个独立的“墙”碰撞器,才是问题所在。至于其余的逻辑,我没有试图破译它,因此我不能对此发表评论。

当宇宙飞船撞上看不见的墙时,你想阻止它们吗?或者像视频中那样消失?@cjf93我希望它们在与无形墙碰撞时停止,然后在地形的另一侧返回并移动到无形墙的另一侧,然后在与无形墙碰撞时再次返回,等等。就像巡逻风格一样。我用我对你的解决方案做了什么,在哪里以及如何添加变量,以及我在Start函数和MoveShips函数中做了什么来更新我的问题。如果你能检查一下我是否正确地添加了变量,如果我在Start函数中正确地添加了变量,那么在Start函数中就会出现错误。“谢谢你。”最后一个回答是的。我说的
size
当然是指
TerrainData.size
。更新了答案。您应该在
withTag
之后添加检查:
terrain=withTag.GetComponent(terrain)好,现在几乎可以工作了。首先,当它与墙碰撞时,它会向后移动,但仅移动到起始位置。我想让它一直向后移动到地形的另一侧,与另一侧的另一面墙碰撞,然后再回到另一面墙,依此类推。另一件事是如何让太空船通过lerp或其他可以让飞船在某一轮中转弯的东西来转弯?@lostLostTit检查
下边界,因为它控制着飞船返回的程度。如果要将地形对象放入编辑器中的脚本中,也可以完全删除
地形
配置。至于平滑旋转,当它们到达边界时,您可能需要添加一个额外的命令,调用它们的
transform.Rotate()
类似于
transform.Rotate(Vector3.up*Time.deltaTime*rotationSpeed)
boundLower = terrain.transform.position - terrain.TerrainData.size / 2;
boundUpper = terrain.transform.position + terrain.TerrainData.size / 2;
var withTag = GameObject.FindWithTag("Terrain");
if (withTag == null)
    throw new InvalidOperationException("Terrain not found");