admin管理员组文章数量:1387301
I'm trying to rotate the object, that were detected by my raycast. I use the Lerp function, but it doesn't work as I want and I don't know why. I saw the same question, but the problem was that the lerp function was used in the start function, instead of the update function. My function seemed to be running in an update, so I don't understand what the problem is. I'm relatively new to unity, so maybe the answer is obvious, but not for me.
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using static UnityEngine.GraphicsBuffer;
public class PlayerInteraction : MonoBehaviour
{
[Header("Camera settings")]
public Camera playerCamera;
[Header("Raycast")]
private Ray cameraRay;
private Vector3 rayStartPosition = new Vector3(Screen.width / 2, Screen.height / 2, 0);
private float lengthOfRay = 5f;
private RaycastHit raycastedObject;
private string objectTag;
private GameObject hittedObject;
[Header("Interaction")]
private KeyCode interactionKey = KeyCode.E;
[Header("Door settings")]
private Quaternion startRotation;
private Quaternion targetOpen;
void Start()
{
}
void Update()
{
RotationOfObject();
}
public void RotationOfObject()
{
cameraRay = playerCamera.ScreenPointToRay(rayStartPosition);
if (Physics.Raycast(cameraRay, out raycastedObject, lengthOfRay) && Input.GetKeyDown(interactionKey))
{
hittedObject = raycastedObject.collider.gameObject;
startRotation = hittedObject.transform.rotation;
targetOpen = new Quaternion(hittedObject.transform.rotation.x, hittedObject.transform.rotation.y + 90f, hittedObject.transform.rotation.z, 0);
hittedObject.transform.rotation = Quaternion.Lerp(startRotation, targetOpen, 0.01f);
}
}
}
I'm trying to rotate the object, that were detected by my raycast. I use the Lerp function, but it doesn't work as I want and I don't know why. I saw the same question, but the problem was that the lerp function was used in the start function, instead of the update function. My function seemed to be running in an update, so I don't understand what the problem is. I'm relatively new to unity, so maybe the answer is obvious, but not for me.
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using static UnityEngine.GraphicsBuffer;
public class PlayerInteraction : MonoBehaviour
{
[Header("Camera settings")]
public Camera playerCamera;
[Header("Raycast")]
private Ray cameraRay;
private Vector3 rayStartPosition = new Vector3(Screen.width / 2, Screen.height / 2, 0);
private float lengthOfRay = 5f;
private RaycastHit raycastedObject;
private string objectTag;
private GameObject hittedObject;
[Header("Interaction")]
private KeyCode interactionKey = KeyCode.E;
[Header("Door settings")]
private Quaternion startRotation;
private Quaternion targetOpen;
void Start()
{
}
void Update()
{
RotationOfObject();
}
public void RotationOfObject()
{
cameraRay = playerCamera.ScreenPointToRay(rayStartPosition);
if (Physics.Raycast(cameraRay, out raycastedObject, lengthOfRay) && Input.GetKeyDown(interactionKey))
{
hittedObject = raycastedObject.collider.gameObject;
startRotation = hittedObject.transform.rotation;
targetOpen = new Quaternion(hittedObject.transform.rotation.x, hittedObject.transform.rotation.y + 90f, hittedObject.transform.rotation.z, 0);
hittedObject.transform.rotation = Quaternion.Lerp(startRotation, targetOpen, 0.01f);
}
}
}
Share
Improve this question
edited Mar 17 at 17:12
ipodtouch0218
3,3709 gold badges14 silver badges29 bronze badges
asked Mar 17 at 16:51
dmitry rubanovdmitry rubanov
251 silver badge5 bronze badges
1 Answer
Reset to default 1Your rotation logic is indeed inside of Update
, but it's also inside the Input.GetKeyDown(interactionKey)
and Physics.Raycast
checks- rotation is only possible on the single frame where you pressed the interaction key.
What you'd want to do instead is keep track of where the door should be, probably through the use of a boolean isOpen;
variable, and move it towards that destination inside of Update
(without it being inside of the if
statement that contains the raycast/key checks). Quaternion.RotateTowards is great for this.
As well, we should also move the door-opening logic to its own behaviour attached to the door itself, instead of having the PlayerInteraction
class also be responsible for rotating the door.
For example:
public class PlayerInteraction : MonoBehaviour
{
// ... your other variables here
public void Update() {
// Check for interaction
if (Input.GetKeyDown(interactionKey))
{
TryInteractWithObject();
}
}
public void TryInteractWithObject()
{
Ray cameraRay = playerCamera.ScreenPointToRay(rayStartPosition);
if (Physics.Raycast(cameraRay, out raycastedObject, lengthOfRay))
{
GameObject hitObject = raycastedObject.collider.gameObject;
// Try to find the "interactable" attached to the object hit
// by the raycast. If the object isn't "interactable", this
// if statement will not run.
if (hitObject.TryGetComponent(out IInteractableObject interactable))
{
interactable.Interact();
}
}
}
}
And for the door, we can make a new Door
MonoBehaviour, along with an IInteractableObject
interface. This interface will allow any new behaviour to be "interactable" by simply inheriting from the interface (and implementing Interact()
), not just the door:
public interface IInteractableObject
{
// This function will be called when a player interacts with this object.
void Interact();
}
public class Door : MonoBehaviour, IInteractableObject
{
[SerializeField] private float doorRotationSpeed = 500f; // In degrees per second
private Quaternion initialRotation, targetRotation;
private bool isOpen;
public void Start()
{
initialRotation = transform.rotation;
targetRotation = transform.rotation;
}
public void Update()
{
// Slowly rotate towards our desired rotation
transform.rotation = Quaternion.RotateTowards(
transform.rotation,
targetRotation,
doorRotationSpeed * Time.deltaTime);
}
public void Interact()
{
// Invert the "isOpen" boolean
isOpen = !isOpen;
if (isOpen)
{
// Door is now open- add 90 degrees on the Y axis.
targetRotation = initialRotation * Quaternion.AngleAxis(90, Vector3.up);
}
else
{
// Door is now closed- reset to starting rotation
targetRotation = initialRotation;
}
}
}
An alternative to putting the rotation logic in Update
would be putting it in a Coroutine, but I recommend doing it this way first, so you can learn the pattern of starting something once and continuing it across Update
calls.
本文标签: cWhy the object doesn39t rotate smoothlyStack Overflow
版权声明:本文标题:c# - Why the object doesn't rotate smoothly? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744545271a2611859.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论