在双手之间移动物体
Moving objects between hands
本质上,我正在尝试在当前功能齐全的两个 "hands" 之间移动一个对象。我可以拿起物体并在房间内 space 和旋转地操纵它们。
但是,我遇到的问题是在控制器之间传输对象。
我可以将物体交给另一只手,但是如果我松开原来那只手的扳机,物体就会变成非运动并掉回地板上。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
public class HandGrab : MonoBehaviour
{
// Variable for Controller button register
public string buttonName;
// Allows objects to be transferred between hands
public HandGrab secondaryHandRef;
// Determines the referenced object type
public XRNode nodeType;
// This affects the distance of object grab from controller
public Vector3 objectGrabOffset;
// Default grab distance relative to the controller, (Where the collider sphere is) This can be changed to affect the visuals and where the items get manipulated from
public float grabDistance = 0.1f;
// Force at which an object is thrown
public float throwingMultiplier = 1.5f;
// To determine if object has been grabbed or cant be grabbed
public string grabName = "Grabbing";
// Stores the values of the currently grabbed object
public Transform CurrentGrabObject
{
get { return _currentlyHeldObject; }
set { _currentlyHeldObject = value; }
}
// Does as it says and stores the last frame and is used to work out velocity calculations
private Vector3 _lastFramePosition;
// Determines the transform values for the currently selected objects
private Transform _currentlyHeldObject;
// bolean to determine if an object is currently being held
private bool _isHeld;
// *Hopefully gets the roation of the controllers and matches that to the roation of the item*
// *private Transform _objectRotation;*
// Use this for initialization
void Start()
{
// Clearing all variables back to zero
_currentlyHeldObject = null;
_lastFramePosition = transform.position;
_isHeld = false;
// Determining the tracking space available
XRDevice.SetTrackingSpaceType(TrackingSpaceType.RoomScale);
}
// Update is called once per frame
void Update()
{
// rotation and position tracking. Updates every frame, should be 90fps
transform.localPosition = InputTracking.GetLocalPosition(nodeType);
transform.localRotation = InputTracking.GetLocalRotation(nodeType);
// Check the object in hand variable. If hand is empty, check to see if we can pick anything up (Object highlight posibilites)
if (_currentlyHeldObject == null)
{
// Check to see if there are any colliders in the proximity of hands
Collider[] colliders = Physics.OverlapSphere(transform.position, grabDistance);
if (colliders.Length > 0)
{
// If there is a collision, then pickup the object if we press the grab button and give it the tag "Grabbing"
if (Input.GetAxis(buttonName) >= 0.5F && colliders[0].transform.CompareTag(grabName))
{
// Now we set to grabbing to true
if (_isHeld)
{
return;
}
_isHeld = true;
// Sets the current object to the object we have just picked up and binds it as a child object (this should allow all rotation to mimic the hands)
colliders[0].transform.SetParent(transform);
// If there is no RigidBody attached to the current object, then assign it a RigidBody variable
if (colliders[0].GetComponent<Rigidbody>() == null)
{
colliders[0].gameObject.AddComponent<Rigidbody>();
}
// Disable all physics on the grabbed object until it is released (May need to change if we want to enable objects to be swung and hit other "live objects")
colliders[0].GetComponent<Rigidbody>().isKinematic = true;
// Save the current object for a reference later
_currentlyHeldObject = colliders[0].transform;
// If other hand grabs the object, then release the object to be able to be re-parented above
if (secondaryHandRef.CurrentGrabObject != null)
{
secondaryHandRef.CurrentGrabObject = null;
}
}
}
}
else
// We must now have an object in our hand at this point. We now update its current position to the current hand poistion + the offset definded above
{
//If we release the grab button, we drop the object here
if (Input.GetAxis(buttonName) < 0.1f)
{
// Return the value of the object back to Non-Kinematic and re-enable physics
Rigidbody _objectRB = _currentlyHeldObject.GetComponent<Rigidbody>();
_objectRB.isKinematic = false;
_objectRB.collisionDetectionMode = CollisionDetectionMode.Continuous;
// Fun stuff starts here, we now calculate the hands current velocity
Vector3 velocity = (transform.position - _lastFramePosition) / Time.deltaTime;
// We now set that object velocity to the current velocity of the hand (I may adjust this to improve physics simulation)
_objectRB.velocity = velocity * throwingMultiplier;
// Kill the reference and revert the hands back to being empty and remove its parent
_currentlyHeldObject.SetParent(null);
_currentlyHeldObject = null;
}
}
//Release the grab function
if (Input.GetAxis(buttonName) < 0.5f && _isHeld)
{
_isHeld = false;
}
// Store the current position of the hand for velocity calculation in the upcoming frame
_lastFramePosition = transform.position;
//Tying off all loose ends here
}
}
在你的更新函数中:
if (_currentlyHeldObject != null && !_currentlyHeldObject.GetComponent<Rigidbody>().isKinematic) {
_currentlyHeldObject.GetComponent<Rigidbody>().isKinematic = true;
}
本质上,我正在尝试在当前功能齐全的两个 "hands" 之间移动一个对象。我可以拿起物体并在房间内 space 和旋转地操纵它们。
但是,我遇到的问题是在控制器之间传输对象。
我可以将物体交给另一只手,但是如果我松开原来那只手的扳机,物体就会变成非运动并掉回地板上。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
public class HandGrab : MonoBehaviour
{
// Variable for Controller button register
public string buttonName;
// Allows objects to be transferred between hands
public HandGrab secondaryHandRef;
// Determines the referenced object type
public XRNode nodeType;
// This affects the distance of object grab from controller
public Vector3 objectGrabOffset;
// Default grab distance relative to the controller, (Where the collider sphere is) This can be changed to affect the visuals and where the items get manipulated from
public float grabDistance = 0.1f;
// Force at which an object is thrown
public float throwingMultiplier = 1.5f;
// To determine if object has been grabbed or cant be grabbed
public string grabName = "Grabbing";
// Stores the values of the currently grabbed object
public Transform CurrentGrabObject
{
get { return _currentlyHeldObject; }
set { _currentlyHeldObject = value; }
}
// Does as it says and stores the last frame and is used to work out velocity calculations
private Vector3 _lastFramePosition;
// Determines the transform values for the currently selected objects
private Transform _currentlyHeldObject;
// bolean to determine if an object is currently being held
private bool _isHeld;
// *Hopefully gets the roation of the controllers and matches that to the roation of the item*
// *private Transform _objectRotation;*
// Use this for initialization
void Start()
{
// Clearing all variables back to zero
_currentlyHeldObject = null;
_lastFramePosition = transform.position;
_isHeld = false;
// Determining the tracking space available
XRDevice.SetTrackingSpaceType(TrackingSpaceType.RoomScale);
}
// Update is called once per frame
void Update()
{
// rotation and position tracking. Updates every frame, should be 90fps
transform.localPosition = InputTracking.GetLocalPosition(nodeType);
transform.localRotation = InputTracking.GetLocalRotation(nodeType);
// Check the object in hand variable. If hand is empty, check to see if we can pick anything up (Object highlight posibilites)
if (_currentlyHeldObject == null)
{
// Check to see if there are any colliders in the proximity of hands
Collider[] colliders = Physics.OverlapSphere(transform.position, grabDistance);
if (colliders.Length > 0)
{
// If there is a collision, then pickup the object if we press the grab button and give it the tag "Grabbing"
if (Input.GetAxis(buttonName) >= 0.5F && colliders[0].transform.CompareTag(grabName))
{
// Now we set to grabbing to true
if (_isHeld)
{
return;
}
_isHeld = true;
// Sets the current object to the object we have just picked up and binds it as a child object (this should allow all rotation to mimic the hands)
colliders[0].transform.SetParent(transform);
// If there is no RigidBody attached to the current object, then assign it a RigidBody variable
if (colliders[0].GetComponent<Rigidbody>() == null)
{
colliders[0].gameObject.AddComponent<Rigidbody>();
}
// Disable all physics on the grabbed object until it is released (May need to change if we want to enable objects to be swung and hit other "live objects")
colliders[0].GetComponent<Rigidbody>().isKinematic = true;
// Save the current object for a reference later
_currentlyHeldObject = colliders[0].transform;
// If other hand grabs the object, then release the object to be able to be re-parented above
if (secondaryHandRef.CurrentGrabObject != null)
{
secondaryHandRef.CurrentGrabObject = null;
}
}
}
}
else
// We must now have an object in our hand at this point. We now update its current position to the current hand poistion + the offset definded above
{
//If we release the grab button, we drop the object here
if (Input.GetAxis(buttonName) < 0.1f)
{
// Return the value of the object back to Non-Kinematic and re-enable physics
Rigidbody _objectRB = _currentlyHeldObject.GetComponent<Rigidbody>();
_objectRB.isKinematic = false;
_objectRB.collisionDetectionMode = CollisionDetectionMode.Continuous;
// Fun stuff starts here, we now calculate the hands current velocity
Vector3 velocity = (transform.position - _lastFramePosition) / Time.deltaTime;
// We now set that object velocity to the current velocity of the hand (I may adjust this to improve physics simulation)
_objectRB.velocity = velocity * throwingMultiplier;
// Kill the reference and revert the hands back to being empty and remove its parent
_currentlyHeldObject.SetParent(null);
_currentlyHeldObject = null;
}
}
//Release the grab function
if (Input.GetAxis(buttonName) < 0.5f && _isHeld)
{
_isHeld = false;
}
// Store the current position of the hand for velocity calculation in the upcoming frame
_lastFramePosition = transform.position;
//Tying off all loose ends here
}
}
在你的更新函数中:
if (_currentlyHeldObject != null && !_currentlyHeldObject.GetComponent<Rigidbody>().isKinematic) {
_currentlyHeldObject.GetComponent<Rigidbody>().isKinematic = true;
}