在 Unity3D 中打开一扇前后门,类似于 Amnesia
Open a Door Front and Back in Unity3D similar to Amnesia
我正在尝试实现类似于失忆症的功能:黑暗后裔让玩家按住鼠标按钮并在门上向前或向后拖动以打开它(如果您不熟悉,请参阅 Door Example 大约 36:30).
我有下面的代码,它有点用,但是开头有点抖动,有点来回跳动,我不知道我是否在使用 transform.Rotate 不正确:
if (previousMousePosition == garbageVector) // if this is the first frame, create a reference for previousMousePosition
previousMousePosition = Input.mousePosition;
else
{
// else find the difference and rotate
rotationAmount = (Input.mousePosition.x - previousMousePosition.x);
if (rotationAmount < 0)
this.transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime);
else if (rotationAmount > 0)
this.transform.Rotate(Vector3.down * rotationSpeed * Time.deltaTime);
}
注意:此脚本附在相关门上。
此外,我的代码在确定旋转时没有考虑玩家在门的哪一侧。有人对我可以从哪里开始有任何建议吗?
您问题中的代码太小,无法完成。您可以通过更改 transform.localEulerAngles
轻松实现的任何方式。我在这个答案中附加的代码可以做到这一点。 T 测试脚本,按照下面的说明进行操作。这也描述了如何确定前门和后门。
1。创建一个简单的立方体,命名为 Door。
2.删除自动附加到新创建的cube/Door.
的Box Collider
3。 Select 门,右键单击并单击“创建空”。将该新游戏对象重命名为 FrontCollider
。确保 FrontCollider
现在是 Door GameObject 的子对象。
4.Select FrontCollider
,给它加上BoxCollider。将 Collider 定位到门的前面(相机前面)。
5。复制 FrontCollider
并 重命名 新游戏对象 BackCollider
。然后将 BackCollider
GameObject 移动到 Door GameObject 的后面。
确保对齐良好的最佳方法是,如果 FrontCollider
的 z 位置为 -2,则将 BackCollider
的 z 位置设置为 2。因此,您要做的就是更改 [的 z 位置=13=] 和 BackCollider
对撞机彼此相对。
5。创建一个空的 GameObject 并将其命名为 Door Parent 确保它不是任何 GameObject 的子对象。我们需要使用此游戏对象将门的轴心点更改为左侧。这样门实际上会像门一样旋转(一侧),而不是绕着它自己的中心旋转。
6。使用移动工具并将 Door Parent 游戏对象移动到门的左侧。不要旋转它。移动它。一旦您认为 Door Parent 现在所在的位置就是 Door 应该旋转的位置,请将下面的 Door Script
附加到 Door Parent 游戏对象不是 Door 游戏对象。
7。将 FrontCollider
GameObject 拖到脚本中的 frontDoorCollider 插槽中。
将 BackCollider
GameObject 拖到脚本中的 backDoorColliderin 插槽中。就是这样。
站在门前,click
、hold
、move
鼠标按下,会PULL开门.向上移动它会关闭它。
站在门后面时,click
、hold
和move
鼠标向上,会推门打开。向上移动它会关闭它。
public class Door : MonoBehaviour
{
public float ySensitivity = 300f;
public float frontOpenPosLimit = 45;
public float backOpenPosLimit = 45;
public GameObject frontDoorCollider;
public GameObject backDoorCollider;
bool moveDoor = false;
DoorCollision doorCollision = DoorCollision.NONE;
// Use this for initialization
void Start()
{
StartCoroutine(doorMover());
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Debug.Log("Mouse down");
RaycastHit hitInfo = new RaycastHit();
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo))
{
if (hitInfo.collider.gameObject == frontDoorCollider)
{
moveDoor = true;
Debug.Log("Front door hit");
doorCollision = DoorCollision.FRONT;
}
else if (hitInfo.collider.gameObject == backDoorCollider)
{
moveDoor = true;
Debug.Log("Back door hit");
doorCollision = DoorCollision.BACK;
}
else
{
doorCollision = DoorCollision.NONE;
}
}
}
if (Input.GetMouseButtonUp(0))
{
moveDoor = false;
Debug.Log("Mouse up");
}
}
IEnumerator doorMover()
{
bool stoppedBefore = false;
float yRot = 0;
while (true)
{
if (moveDoor)
{
stoppedBefore = false;
Debug.Log("Moving Door");
yRot += Input.GetAxis("Mouse Y") * ySensitivity * Time.deltaTime;
//Check if this is front door or back
if (doorCollision == DoorCollision.FRONT)
{
Debug.Log("Pull Down(PULL TOWARDS)");
yRot = Mathf.Clamp(yRot, -frontOpenPosLimit, 0);
Debug.Log(yRot);
transform.localEulerAngles = new Vector3(0, -yRot, 0);
}
else if (doorCollision == DoorCollision.BACK)
{
Debug.Log("Pull Up(PUSH AWAY)");
yRot = Mathf.Clamp(yRot, 0, backOpenPosLimit);
Debug.Log(yRot);
transform.localEulerAngles = new Vector3(0, yRot, 0);
}
}
else
{
if (!stoppedBefore)
{
stoppedBefore = true;
Debug.Log("Stopped Moving Door");
}
}
yield return null;
}
}
enum DoorCollision
{
NONE, FRONT, BACK
}
}
我正在尝试实现类似于失忆症的功能:黑暗后裔让玩家按住鼠标按钮并在门上向前或向后拖动以打开它(如果您不熟悉,请参阅 Door Example 大约 36:30).
我有下面的代码,它有点用,但是开头有点抖动,有点来回跳动,我不知道我是否在使用 transform.Rotate 不正确:
if (previousMousePosition == garbageVector) // if this is the first frame, create a reference for previousMousePosition
previousMousePosition = Input.mousePosition;
else
{
// else find the difference and rotate
rotationAmount = (Input.mousePosition.x - previousMousePosition.x);
if (rotationAmount < 0)
this.transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime);
else if (rotationAmount > 0)
this.transform.Rotate(Vector3.down * rotationSpeed * Time.deltaTime);
}
注意:此脚本附在相关门上。
此外,我的代码在确定旋转时没有考虑玩家在门的哪一侧。有人对我可以从哪里开始有任何建议吗?
您问题中的代码太小,无法完成。您可以通过更改 transform.localEulerAngles
轻松实现的任何方式。我在这个答案中附加的代码可以做到这一点。 T 测试脚本,按照下面的说明进行操作。这也描述了如何确定前门和后门。
1。创建一个简单的立方体,命名为 Door。
2.删除自动附加到新创建的cube/Door.
的Box Collider
3。 Select 门,右键单击并单击“创建空”。将该新游戏对象重命名为 FrontCollider
。确保 FrontCollider
现在是 Door GameObject 的子对象。
4.Select FrontCollider
,给它加上BoxCollider。将 Collider 定位到门的前面(相机前面)。
5。复制 FrontCollider
并 重命名 新游戏对象 BackCollider
。然后将 BackCollider
GameObject 移动到 Door GameObject 的后面。
确保对齐良好的最佳方法是,如果 FrontCollider
的 z 位置为 -2,则将 BackCollider
的 z 位置设置为 2。因此,您要做的就是更改 [的 z 位置=13=] 和 BackCollider
对撞机彼此相对。
5。创建一个空的 GameObject 并将其命名为 Door Parent 确保它不是任何 GameObject 的子对象。我们需要使用此游戏对象将门的轴心点更改为左侧。这样门实际上会像门一样旋转(一侧),而不是绕着它自己的中心旋转。
6。使用移动工具并将 Door Parent 游戏对象移动到门的左侧。不要旋转它。移动它。一旦您认为 Door Parent 现在所在的位置就是 Door 应该旋转的位置,请将下面的 Door Script
附加到 Door Parent 游戏对象不是 Door 游戏对象。
7。将 FrontCollider
GameObject 拖到脚本中的 frontDoorCollider 插槽中。
将 BackCollider
GameObject 拖到脚本中的 backDoorColliderin 插槽中。就是这样。
站在门前,click
、hold
、move
鼠标按下,会PULL开门.向上移动它会关闭它。
站在门后面时,click
、hold
和move
鼠标向上,会推门打开。向上移动它会关闭它。
public class Door : MonoBehaviour
{
public float ySensitivity = 300f;
public float frontOpenPosLimit = 45;
public float backOpenPosLimit = 45;
public GameObject frontDoorCollider;
public GameObject backDoorCollider;
bool moveDoor = false;
DoorCollision doorCollision = DoorCollision.NONE;
// Use this for initialization
void Start()
{
StartCoroutine(doorMover());
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Debug.Log("Mouse down");
RaycastHit hitInfo = new RaycastHit();
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo))
{
if (hitInfo.collider.gameObject == frontDoorCollider)
{
moveDoor = true;
Debug.Log("Front door hit");
doorCollision = DoorCollision.FRONT;
}
else if (hitInfo.collider.gameObject == backDoorCollider)
{
moveDoor = true;
Debug.Log("Back door hit");
doorCollision = DoorCollision.BACK;
}
else
{
doorCollision = DoorCollision.NONE;
}
}
}
if (Input.GetMouseButtonUp(0))
{
moveDoor = false;
Debug.Log("Mouse up");
}
}
IEnumerator doorMover()
{
bool stoppedBefore = false;
float yRot = 0;
while (true)
{
if (moveDoor)
{
stoppedBefore = false;
Debug.Log("Moving Door");
yRot += Input.GetAxis("Mouse Y") * ySensitivity * Time.deltaTime;
//Check if this is front door or back
if (doorCollision == DoorCollision.FRONT)
{
Debug.Log("Pull Down(PULL TOWARDS)");
yRot = Mathf.Clamp(yRot, -frontOpenPosLimit, 0);
Debug.Log(yRot);
transform.localEulerAngles = new Vector3(0, -yRot, 0);
}
else if (doorCollision == DoorCollision.BACK)
{
Debug.Log("Pull Up(PUSH AWAY)");
yRot = Mathf.Clamp(yRot, 0, backOpenPosLimit);
Debug.Log(yRot);
transform.localEulerAngles = new Vector3(0, yRot, 0);
}
}
else
{
if (!stoppedBefore)
{
stoppedBefore = true;
Debug.Log("Stopped Moving Door");
}
}
yield return null;
}
}
enum DoorCollision
{
NONE, FRONT, BACK
}
}