C# 空中曲棍球-球员球棒移动过快时穿过冰球
我现在正在Unity3d开发一款空中曲棍球游戏。我遇到的问题是,当球员试图太快地击中冰球时,球员最终会穿过冰球,因此不会发生碰撞。如果玩家静止不动,冰球击中玩家,或者玩家以缓慢的速度击中冰球,游戏就会如预期的那样完美 玩家有一个刚体,使用胶囊对撞机进行连续碰撞检测。该冰球还具有具有连续动态碰撞检测的刚体和具有凸面的网格碰撞器 我尝试将fixed timestep设置为0.01,但没有效果。以下是玩家移动的脚本:C# 空中曲棍球-球员球棒移动过快时穿过冰球,c#,unity3d,C#,Unity3d,我现在正在Unity3d开发一款空中曲棍球游戏。我遇到的问题是,当球员试图太快地击中冰球时,球员最终会穿过冰球,因此不会发生碰撞。如果玩家静止不动,冰球击中玩家,或者玩家以缓慢的速度击中冰球,游戏就会如预期的那样完美 玩家有一个刚体,使用胶囊对撞机进行连续碰撞检测。该冰球还具有具有连续动态碰撞检测的刚体和具有凸面的网格碰撞器 我尝试将fixed timestep设置为0.01,但没有效果。以下是玩家移动的脚本: void ObjectFollowCursor() { Ray ray =
void ObjectFollowCursor()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Vector3 point = ray.origin + (ray.direction * distance);
Vector3 temp = point;
temp.y = 0.2f; // limits player on y axis
cursorObject.position = temp;
}
这是冰球与玩家碰撞时的代码:
// If puck hits player
if(collision.gameObject.tag == "Player")
{
Vector3 forceVec = this.GetComponent<Rigidbody>().velocity.normalized * hitForce;
rb.AddForce(forceVec, ForceMode.Impulse);
Debug.Log ("Player Hit");
}
//如果冰球击中玩家
如果(collision.gameObject.tag==“Player”)
{
Vector3 forceVec=this.GetComponent().velocity.normalized*hitForce;
rb.AddForce(forceVec,ForceMode.pulse);
Log(“玩家命中”);
}
任何帮助都将不胜感激。谢谢 您遇到的问题称为“隧道” 这是因为您的对象正在高速移动,并且在该特定帧中未检测到碰撞。在帧
n
中,球正好在球棒前面,但当计算帧n+1
时,球已经移动到球棒后面,因此完全“错过”碰撞
这是一个常见的问题,但也有解决办法
我建议你学习这个脚本,并尝试在游戏中实现它
这不是我的代码:
来源:
使用UnityEngine;
使用系统集合;
公共课不做粗野的事:单一行为
{
//将此设置为true时请小心-它可能会导致双重错误
//要激发的事件-但它不会通过触发器
public bool sendTriggerMessage=false;
public LayerMask LayerMask=-1;//确保我们不在此层中
public float skinWidth=0.1f;//可能不需要更改
私人浮动最小范围;
私人浮动部分帐篷;
私人浮动sqrmimextent;
私有向量3先前位置;
私人刚体;
私人对撞机;
//初始化值
void Start()
{
myRigidbody=GetComponent();
myCollider=GetComponent();
previousPosition=myRigidbody.position;
minimumExtent=Mathf.Min(Mathf.Min(myCollider.bounds.extends.x,myCollider.bounds.extends.y),myCollider.bounds.extends.z);
partialExtent=最小范围*(1.0f-皮肤宽度);
SQrMinimExtent=最小范围*最小范围;
}
void FixedUpdate()
{
//我们的行动是否超过了我们的最低限度?
Vector3 movementThisStep=myRigidbody.position-上一个位置;
浮动移动sqrMagnitude=移动ThisStep.sqrMagnitude;
如果(移动SQRMagnitude>SQRMimumExtent)
{
float movementMagnitude=数学Sqrt(movementSqrMagnitude);
RaycastHitInfo;
//检查我们可能错过的障碍物
if(Physics.Raycast(上一个位置、移动此步骤、输出hitInfo、移动幅度、图层任务值))
{
if(!hitInfo.collider)
返回;
if(hitInfo.collider.isTrigger)
hitInfo.collider.SendMessage(“OnTriggerEnter”,myCollider);
if(!hitInfo.collider.isTrigger)
myRigidbody.position=hitInfo.point-(移动此步骤/移动幅度)*部分内容;
}
}
previousPosition=myRigidbody.position;
}
}
您尝试连续碰撞检测(CCD)是正确的。有一些限制(特别是在这种情况下,您希望将CCD用于两个移动对象,而不是一个移动对象和一个静态对象),但它是针对这种情况设计的。进入这些约束:
将碰撞检测模式设置为“连续”,以防止碰撞
刚体通过任何静态物体(即非刚体)
网络对撞机。将其设置为“连续动态”也可防止
刚体通过任何其他受支持的刚体时
碰撞检测模式设置为连续或连续动态。
长方体、球体和球体支持连续碰撞检测
胶囊准直器
总而言之,冰球和桨叶都需要设置为连续动态,并且都需要是盒子、球体或胶囊对撞机。如果你能让这些约束在你的游戏中发挥作用,你应该能够在不需要自己编写的情况下获得连续的碰撞检测
关于Unity的CCD的注释值得重复: 请注意,连续碰撞检测旨在作为安全网 在对象可能通过的情况下捕捉碰撞 通过彼此,但不会产生物理上精确的碰撞 结果,因此您可能仍然考虑减少固定时间步长。 时间管理器检查器中的值,以使模拟更精确 精确,如果您遇到快速移动对象的问题
但是,由于您是手动指定碰撞反应,这可能不是问题。距离变量从何处获取?这只是用于限制玩家可以在桌子上移动的距离。哦,好的,我没有意识到连续碰撞检测不支持网格碰撞器。玩家是一个球体对撞机,我一直在努力让冰球像球体对撞机一样工作,但它只是没有按它应该的方式工作。我会继续胡闹,看看能不能让它按我想要的方式运行。谢谢你的帮助。最后我让球体对撞机以我想要的方式与冰球一起工作。然后,我将固定时间步长从0.02更改为0.01,结果已更改
using UnityEngine;
using System.Collections;
public class DontGoThroughThings : MonoBehaviour
{
// Careful when setting this to true - it might cause double
// events to be fired - but it won't pass through the trigger
public bool sendTriggerMessage = false;
public LayerMask layerMask = -1; //make sure we aren't in this layer
public float skinWidth = 0.1f; //probably doesn't need to be changed
private float minimumExtent;
private float partialExtent;
private float sqrMinimumExtent;
private Vector3 previousPosition;
private Rigidbody myRigidbody;
private Collider myCollider;
//initialize values
void Start()
{
myRigidbody = GetComponent<Rigidbody>();
myCollider = GetComponent<Collider>();
previousPosition = myRigidbody.position;
minimumExtent = Mathf.Min(Mathf.Min(myCollider.bounds.extents.x, myCollider.bounds.extents.y), myCollider.bounds.extents.z);
partialExtent = minimumExtent * (1.0f - skinWidth);
sqrMinimumExtent = minimumExtent * minimumExtent;
}
void FixedUpdate()
{
//have we moved more than our minimum extent?
Vector3 movementThisStep = myRigidbody.position - previousPosition;
float movementSqrMagnitude = movementThisStep.sqrMagnitude;
if (movementSqrMagnitude > sqrMinimumExtent)
{
float movementMagnitude = Mathf.Sqrt(movementSqrMagnitude);
RaycastHit hitInfo;
//check for obstructions we might have missed
if (Physics.Raycast(previousPosition, movementThisStep, out hitInfo, movementMagnitude, layerMask.value))
{
if (!hitInfo.collider)
return;
if (hitInfo.collider.isTrigger)
hitInfo.collider.SendMessage("OnTriggerEnter", myCollider);
if (!hitInfo.collider.isTrigger)
myRigidbody.position = hitInfo.point - (movementThisStep / movementMagnitude) * partialExtent;
}
}
previousPosition = myRigidbody.position;
}
}