我正在跟随凯西·哈德曼用Unity和C#从游戏编程中创建障碍游戏。我已经在第16章的前几页达到了你创建一个危险来杀死玩家的地步。在开始阶段,你编写了一段代码,如果玩家对象与障碍物碰撞,就杀死玩家对象。(据我所知)完全正确,然而当我创建一个球体作为测试危险,将脚本分配给它,并将玩家对象运行到其中时,当它们碰撞时没有发生任何事情。我想可能是危险代码有错误,所以我注解掉了"当与玩家层上的对象碰撞时,杀死玩家"代码,我写了代码,让它在冲突时只写入控制台,并进行了测试。不幸的是,当这两个物体相互接触时,似乎没有任何碰撞检测。我在谷歌上搜索了"物体不碰撞统一体"和我能想到的"碰撞不检测统一体"的每一种组合,没有一个答案有帮助,所以我在这里发帖,希望我能得到一个答案。我包含了这两个对象及其设置的屏幕截图、Unity中的物理设置以及为这两个对象编写的代码,希望有人能发现我做错了什么。
The Player Object
The Test Hazard Object
Layer Collision Matrix
播放器对象脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
//References
[Header("References")]
public Transform trans;
public Transform modelTrans;
public CharacterController characterController;
//Movement
[Header("Movement")]
[Tooltip("Units moved per second at maximum speed.")]
public float movespeed = 24;
[Tooltip("Time, in seconds, to reach maximum speed.")]
public float timeToMaxSpeed = .26f;
private float VelocityGainPerSecond{ get { return movespeed / timeToMaxSpeed; }}
[Tooltip("Time, in seconds, to go from maximum speed to stationary.")]
public float timeToLoseMaxSpeed = .2f;
private float VelocityLossPerSecond { get { return movespeed / timeToLoseMaxSpeed; }}
[Tooltip("Multiplier for momentum when attempting to move in a direction opposite the current traveling direction (e.g. trying to move right when already moving left.")]
public float reverseMomentumMultiplier = 2.2f;
private Vector3 movementVelocity = Vector3.zero;
private void Movement()
{
// IF W or the up arrow key is held:
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
if (movementVelocity.z >= 0) // If we're already moving forward
//Increase Z velocity by VelocityGainPerSecond, but don't go higher than 'moveSpeed':
movementVelocity.z = Mathf.Min(movespeed,movementVelocity.z + VelocityGainPerSecond * Time.deltaTime);
else // Else if we're moving back
//Increase Z velocity by VelocityGainPerSecond, using the reverseMomentumMultiplier, but don't raise higher than 0:
movementVelocity.z = Mathf.Min(0,movementVelocity.z + reverseMomentumMultiplier * Time.deltaTime);
}
//If S or the down arrow key is held:
else if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
if (movementVelocity.z > 0) // If we're already moving forward
movementVelocity.z = Mathf.Max(0,movementVelocity.z - VelocityGainPerSecond * reverseMomentumMultiplier * Time.deltaTime);
else // If we're moving back or not moving at all
movementVelocity.z = Mathf.Max(-movespeed,movementVelocity.z - VelocityGainPerSecond * Time.deltaTime);
}
else //If neither forward nor back are being held
{
//We must bring the Z velocity back to 0 over time.
if (movementVelocity.z > 0) // If we're moving up,
//Decrease Z velocity by VelocityLossPerSecond, but don't go any lower than 0:
movementVelocity.z = Mathf.Max(0,movementVelocity.z - VelocityLossPerSecond * Time.deltaTime);
else //If we're moving down,
//Increase Z velocity (back towards 0) by VelocityLossPerSecond, but don't go any higher than 0:
movementVelocity.z = Mathf.Min(0,movementVelocity.z + VelocityLossPerSecond * Time.deltaTime);
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
if (movementVelocity.x >= 0) //If we're already moving right
//Increase X velocty by VelocityGainPerSecond, but don't go higher than 'movespeed':
movementVelocity.x = Mathf.Min(movespeed,movementVelocity.x + VelocityGainPerSecond * Time.deltaTime);
else //If we're moving left
//Increase X velocity by VelocityGainPerSecond, using the reverseMomentumMultiplier, but don't raise higher than 0:
movementVelocity.x = Mathf.Min(0,movementVelocity.x + VelocityGainPerSecond * reverseMomentumMultiplier * Time.deltaTime);
}
else if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
if (movementVelocity.x > 0) //If we're already moving right
movementVelocity.x = Mathf.Max(0,movementVelocity.x - VelocityGainPerSecond * reverseMomentumMultiplier * Time.deltaTime);
else // If we're moving left or not at all
movementVelocity.x = Mathf.Max(-movespeed,movementVelocity.x - VelocityGainPerSecond * Time.deltaTime);
}
else //If neither left nor right are being held
{
//We must bring the X Velocity back to 0 over time.
if (movementVelocity.x > 0) //If we're moving right,
//Decrease X velocity by VelocityLossPerSecond, but don't go any lower than 0:
movementVelocity.x = Mathf.Max(0,movementVelocity.x - VelocityLossPerSecond * Time.deltaTime);
else //If we're moving left
//Increase X velocity (back towards 0) by VelocityLossPerSecond, but don't go any higher than 0:
movementVelocity.x = Mathf.Min(0,movementVelocity.x + VelocityLossPerSecond * Time.deltaTime);
}
//If the player is moving in either direction (left/right or up/down):
if (movementVelocity.x != 0 || movementVelocity.z != 0)
{
//Applying the movement velocity:
characterController.Move(movementVelocity * Time.deltaTime);
//Keeping the model holder rotated towards the last movement direction:
modelTrans.rotation = Quaternion.Slerp(modelTrans.rotation, Quaternion.LookRotation(movementVelocity), .18F);
}
}
//Death and Respawning
[Header("Death and Respawning")]
[Tooltip("How long after the player's death, in seconds, before they are respawned?")]
public float respawnWaitTime = 2f;
private bool dead = false;
private Vector3 spawnPoint;
private Quaternion spawnRotation;
private void Update()
{
Movement();
}
void Start()
{
spawnPoint = trans.position;
spawnRotation = modelTrans.rotation;
}
public void Die()
{
if (!dead)
{
dead = true;
Invoke("Respawn", respawnWaitTime);
movementVelocity = Vector3.zero;
enabled = false;
characterController.enabled = false;
modelTrans.gameObject.SetActive(false);
}
}
public void Respawn()
{
modelTrans.rotation = spawnRotation;
dead = false;
trans.position = spawnPoint;
enabled = true;
characterController.enabled = true;
modelTrans.gameObject.SetActive(true);
}
}
危险对象脚本:
`using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Hazard : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.layer == 8)
{
//Player player = other.GetComponent<Player>();
//if (player != null)
//player.Die();
Debug.Log("Yay!");
}
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}`
我试过:
向播放器对象添加单独的长方体碰撞器
将刚体添加到一个、两个和其他对象
扯我的头发
重启Unity
重新启动我的计算机
将播放器对象标记为播放器(我看到一个问题看起来和我的问题很相似,所以我想这可能会有帮助;我对Unity或C#还不是很熟悉,所以我不确定什么或为什么会有帮助。)
以上这些都没有让Unity看起来像是在检测这两个对象之间的碰撞。
2条答案
按热度按时间wa7juj8i1#
下面是OnTriggerEnter文档中的一行:
第一个月
您是否尝试过将
Collider
添加到您的播放器中,同时将Rigidbody
组件添加到危险中?68bkxrlz2#
对于
OnTriggerEnter()
,你需要一个选中Is Trigger
的对撞机和一个刚性体。但是这个检查层值被用作位掩码,请阅读here的更多信息。要检查正确的层,您需要按位操作:
使用位运算符时要小心,不要被运算符的优先级所欺骗。
这将对播放器层中的所有对象成功。另一种方法是设置播放器对象的标签并与该标签进行比较: