我想在3D游戏中创建一个推墙。这是一个在超级马里奥64推墙的例子
Pushing Walls in Super Mario 64 (Video on Youtube)
所以这就是检查员的墙壁外观
这是附在推墙上的代码
public class PushingObstacle : MonoBehaviour {
private Vector3 startPoint; // the current position when loading the scene
[SerializeField]
private Vector3 endPoint; // the target point
[SerializeField]
private float forwardSpeed; // speed when moving to the end
[SerializeField]
private float backwardSpeed; // speed when moving back to start
float currentSpeed; // the current speed (forward/backward)
private Vector3 direction; // the direction the wall is moving
private Vector3 destination; // the target point
private Rigidbody obstacleRigid; // rigidbody of the wall
private void Start()
{
startPoint = transform.position;
obstacleRigid = GetComponent<Rigidbody>();
SetDestination(endPoint); // set the target point
}
private void FixedUpdate()
{
obstacleRigid.MovePosition(transform.position + direction * currentSpeed * Time.fixedDeltaTime); // start moving
if (Vector3.Distance(obstacleRigid.position, destination) < currentSpeed * Time.fixedDeltaTime) // set a new target point
SetDestination(destination == startPoint ? endPoint : startPoint);
}
private void SetDestination(Vector3 destinationPoint)
{
destination = destinationPoint;
direction = (destination - transform.position).normalized; // set the movement direction
currentSpeed = destination == endPoint ? forwardSpeed : backwardSpeed; // set the speed
}
}
因此,当玩家移动到墙上并稍微接触它时,墙就会飞走。
我可以在运动模式下设置墙体刚体。但我希望墙壁在推动他时给玩家增加一点力量。我怎样才能实现这两种行为(不会飞离玩家并对玩家施加小小的力量)?
修改
我无法将其设置为运动学,因为当跳到墙顶(立方体)时,播放器不会相对于墙移动。
答案 0 :(得分:2)
这很难。但这是我的解决方案:
Mass = 10
以及角色Mass = 1
空GameObject有一个触发器对撞机,用于检测何时 玩家跳过平台。当发生这种情况时,两个动 地点:
当玩家离开平台的顶部时,它就会停止 Emtpy GameObject的孩子并停止运动
这是选择了Empty GameObject的场景图像,以显示平台顶部的对撞机:
这里是Empty GameObject的检查器
这里是平台的检查员:
这是玩家的检查员:
最后是脚本。
空游戏对象的脚本(用于检测玩家是否在平台上并在场景中放置的两个空游戏对象之间移动平台以确定平台的路径)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class Push : MonoBehaviour {
public Transform target;
public Transform end;
bool movingForward = true;
float speed = 9f;
bool moving = false;
// Update is called once per frame
void Update () {
if(movingForward)
{
//transform.position = new Vector3(transform.position.x + 0.001f, transform.position.y, transform.position.z);
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
if(transform.position.Equals(target.position))
movingForward = false;
}else{
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, end.position, step);
if(transform.position.Equals(end.position))
movingForward = true;
}
}
void OnTriggerEnter(Collider other)
{
print("Something Inside");
if(other.tag == "Player")
{
print("It is the player");
other.gameObject.GetComponent<Rigidbody>().isKinematic=true;
other.gameObject.transform.parent = this.transform;
}
}
void OnTriggerExit(Collider other)
{
if(other.tag == "Player")
{
other.gameObject.GetComponent<Rigidbody>().isKinematic=false;
other.gameObject.transform.parent = null;
}
}
}
现在移动播放器的脚本
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed = 6f;
Vector3 movement;
Rigidbody playerRigidbody;
int floorMask;
float camRaylength = 100f;
float JumpSpeed = 15f;
void Awake()
{
floorMask = LayerMask.GetMask("Floor");
playerRigidbody = GetComponent <Rigidbody> ();
}
void FixedUpdate()
{
float h = Input.GetAxisRaw ("Horizontal");
float v = Input.GetAxisRaw ("Vertical");
Move (h, v);
Turning ();
if(Input.GetKeyDown(KeyCode.Space))
Jump();
}
void Jump()
{
playerRigidbody.isKinematic=false;
playerRigidbody.AddForce(Vector3.up *JumpSpeed);
}
void Move(float h, float v)
{
movement.Set(h, 0f, v);
movement = movement.normalized * speed * Time.deltaTime;
playerRigidbody.MovePosition (transform.position + movement);
}
void Turning()
{
Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit floorHit;
if (Physics.Raycast (camRay, out floorHit, camRaylength, floorMask)) {
Vector3 playerToMouse = floorHit.point - transform.position;
playerToMouse.y = 0f;
Quaternion newRotation = Quaternion.LookRotation (playerToMouse);
playerRigidbody.MoveRotation (newRotation);
}
}
void Animating(float h, float v)
{
bool walking = h != 0f || v != 0f;
}
}
测试它并让我知道是否有任何不清楚
答案 1 :(得分:1)
我相信你的问题是由于玩家的质量与墙壁的质量造成的。确保这些值是相互关联的半实际值。如果你的墙的质量为1,那么尝试将你的玩家的质量设置为0.1,因为显然混凝土墙比平均有机生命形式重得多。
此外,Unity论坛对这些类型的问题往往有更好的结果。我不相信这是您的代码的问题,只是提供给正在使用的对象的值的问题。