我有第一人称玩家可以抓住和携带的物体。光线投射仅检查所有可以拾取的对象都在的一个图层上。
如果物体撞到不在同一层上的物体,则被保留的对象将被丢弃,因为光线不再击中被抓取的物体。这是预期行为。
但是,如果抓取的对象撞到同一图层上的对象,则不会丢弃该对象。我相信这是因为光线继续记录图层上的对象仍然被选中。
如何设置它,以便光线投射知道它已切换对象,并删除当前对象?
任何帮助都非常感谢!
下面是正在发生的事情的示例:
https://reddit.com/link/cgfyg0/video/5zk5ylbh0wb31/player
以下是控制玩家光线投射以检查是否可以抓取对象的代码:
public class PlayerPickUp : MonoBehaviour
{
// Public variables
public float rayLength;
public bool objectSelected;
// Private variables
Camera camera;
RaycastHit hit;
GameObject hitObject;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// Set layerMask as layer 10
int layerMask = 1 << 10;
// Create ray and check for object hit
if( Physics.Raycast(transform.position, transform.TransformDirection( Vector3.forward ), out hit, rayLength, layerMask ) )
{
// Set objectSelected to true
objectSelected = true;
// Set hit object as hitObject
hitObject = hit.collider.gameObject;
// Set hitObject's selectedByPlayer var to true
hitObject.GetComponent<AnimalGrab>().selectedByPlayer = true;
// Draw debug line
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.blue);
}
// Object no longer being selected
else if( objectSelected )
{
// Set objectSelected to false
objectSelected = false;
// Set hitObject's selectedByPlayer var to false
hitObject.GetComponent<AnimalGrab>().selectedByPlayer = false;
}
// Ray has not hit anything
else {
// Sit hit object as empty
hitObject = null;
// Draw debug line
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * rayLength, Color.yellow);
}
}
}
下面是控制要抓取的对象的代码:
public class ObjectGrab : MonoBehaviour
{
// Public variables
public bool beingHeld;
public bool selectedByPlayer;
public GameObject selfObject;
public GameObject tempParentObject;
public GameObject playerObject;
// Private variables
float throwForce;
float lookSpeed;
float targetDistance;
Vector3 selfPosition;
Rigidbody rb;
float selfDistance;
// Start is called before the first frame update
void Start()
{
// Assign rigidbody component
rb = selfObject.GetComponent<Rigidbody>();
// Set beingHeld as false
beingHeld = false;
// Set initial throwForce
throwForce = 1000f;
// Set initial lookSpeed
lookSpeed = 10f;
}
// Update is called once per frame
void Update()
{
// Calculate distance from parent object
selfDistance = Vector3.Distance( selfObject.transform.position, tempParentObject.transform.position );
// If being held
if( beingHeld == true )
{
// Set velocity to 0
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
// Set as child of GrabPoint
selfObject.transform.SetParent(tempParentObject.transform);
// ROTATION
//Distance between target and the actual rotating object
Vector3 targetDistance = playerObject.transform.position - transform.position;
// Calculate the Quaternion for the rotation
Quaternion rot = Quaternion.Slerp( transform.rotation, Quaternion.LookRotation( targetDistance ), lookSpeed * Time.deltaTime );
//Apply the rotation
transform.rotation = rot;
// put 0 on the axis you do not want for the rotation object to rotate
transform.eulerAngles = new Vector3( 0, transform.eulerAngles.y, 0 );
// THROWING
// If right click pressed
if( Input.GetMouseButtonDown( 1 ) )
{
// Add force to self
rb.AddForce( tempParentObject.transform.forward * throwForce );
// Set beingHeld as false
beingHeld = false;
}
}
// If not being held
else
{
selfPosition = selfObject.transform.position;
selfObject.transform.SetParent( null );
rb.useGravity = true;
selfObject.transform.position = selfPosition;
}
// If not being selected by player
if( selectedByPlayer == false )
{
// Set beingHeld as false
beingHeld = false;
}
}
// Mouse Down
void OnMouseDown()
{
if( selectedByPlayer == true )
{
// Set beingHeld as true
beingHeld = true;
// Disable gravity
selfObject.GetComponent<Rigidbody>().useGravity = false;
// Enable collision detection
selfObject.GetComponent<Rigidbody>().detectCollisions = true;
}
}
// Mouse Up
void OnMouseUp()
{
// Set beingHeld as false
beingHeld = false;
}
}
在更新函数的第一个 if 中:
if( Physics.Raycast[...])
您可以执行另一个检查来测试命中对象是否像这样更改:
if(hit.collider.gameObject != hitObject)
{
// The object changed
}
然后在那里处理对象更改。