#c# #unity3d #rotation #transform #game-development
Вопрос:
У меня есть игра в Unity, в которой я добавил три объекта (Куб, Цилиндр, Капсулу). К этим игровым объектам я добавил скрипт для поворота их вдоль оси при нажатии левой кнопки мыши и x, y или z, поворачивая объект вдоль соответствующей оси. Но когда я пытаюсь повернуть один объект, другие объекты тоже вращаются. Как повернуть каждый объект, не затрагивая другие объекты.
if (Input.GetMouseButton(0) amp;amp; Input.GetKey(KeyCode.Z))
{
transform.RotateAround(transform.position, transform.forward, Time.deltaTime * 90f);
}
if (Input.GetMouseButton(0) amp;amp; Input.GetKey(KeyCode.X))
{
transform.RotateAround(transform.position, transform.right, Time.deltaTime * 90f);
}
if (Input.GetMouseButton(0) amp;amp; Input.GetKey(KeyCode.Y))
{
transform.RotateAround(transform.position, transform.up, Time.deltaTime * 90f);
}
Ответ №1:
Я предполагаю, что вы пытаетесь достичь
- щелкните по объекту курсором мыши и удерживайте
- затем поверните этот объект с помощью соответствующих клавиш.
На самом деле для этого вам нужен только один сценарий, не для каждого объекта, а только один в вашей сцене (например, центральный контроллер).
public class ObjectRotator : MonoBehaviour
{
[SerializeField] private Camera _camera;
//Optionally if you only want to hit objects on (a) certain layer(s)
//[SerializeField] private LayerMask layers;
private void Awake ()
{
if(!_camera) _camera = Camera.main;
}
private void Update ()
{
if(Input.GetMouseButton(0))
{
// Shoot a Raycast from the mouse position into your scene to check if you hit an object
var ray = _camera.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out var hit)
// or if using the layer mask
//if(Physics.Raycast(ray, out var hit, float.positiveInfinity, layers)
{
if (Input.GetKey(KeyCode.Z))
{
// Instead of using RotateAround rather use Rotate which rotated around this object's
// pivot position anyway. By default it is in local space so also no need for transform.forward etc
hit.transform.Rotate(Vector3.forward * Time.deltaTime * 90f);
}
if (Input.GetKey(KeyCode.X))
{
hit.transform.Rotate(Vector3.right * Time.deltaTime * 90f);
}
if (Input.GetKey(KeyCode.Y))
{
hit.transform.Rotate(Vector3.up * Time.deltaTime * 90f);
}
}
}
}
}
ПРИМЕЧАНИЕ: Требуется, чтобы ваши целевые объекты имели коллайдеры (и выбранные слои).
В качестве альтернативы, если вы предпочитаете искать решение с одним сценарием на объект, вы могли бы использовать, например
public class Rotation : MonoBehaviour
{
// This is called by Unity when the mouse is going down while hovering this object's collider
private void OnMouseDown ()
{
// Start the RotationRoutine
StartCoroutine (RotationRoutine());
}
// This is called when the mouse button goes up while hovering this object's collider
private void OnMouseUp()
{
// To simplify things just stop any routine started by this behavior
StopAllCoroutines ();
}
// Also stop when the mouse leaves this object's collider while still being pressed
private void OnMouseExit()
{
StopAllCoroutines ();
}
private void RotationRoutine()
{
// Whut?! No worries ;) This is fine in a Coroutine as soon as you "yield" somewhere inside
while(true)
{
if (Input.GetKey(KeyCode.Z))
{
transform.Rotate(Vector3.forward * Time.deltaTime * 90f);
}
if (Input.GetKey(KeyCode.X))
{
transform.Rotate(Vector3.right * Time.deltaTime * 90f);
}
if (Input.GetKey(KeyCode.Y))
{
transform.Rotate(Vector3.up * Time.deltaTime * 90f);
}
// Basically tells Unity to "pause" here, render this frame and
// continue from here in the next frame
yield return null;
}
}
}
Ответ №2:
Попробуйте три отдельных однонаправленных действия с условием ввода Input.GetKey(KeyCode.X)
Input.GetKey(KeyCode.Y)
, Input.GetKey(KeyCode.Z)
соответственно:
if (Input.GetMouseButton(0) amp;amp; Input.GetKey(KeyCode.X)) {
transform.RotateAround(transform.position, transform.forward, Time.deltaTime * 90f);
}
Это transform
относится к преобразованию игрового объекта Monobehvaiour
, к которому он прикреплен, поэтому, если у вас есть сценарий, прикрепленный ко многим игровым объектам, логика применима ко всем из них.
Вам нужно сделать 3 разных Monobehaviours
и обработать входную логику соответственно или создать глобальный Monobehaviour
обработчик вращения, в котором вы сохраняете ссылку для каждого из ваших игровых объектов, чтобы вы могли обрабатывать каждое преобразование соответственно.
Комментарии:
1. Итак, мне нужно создать три разных сценария и прикрепить их к объектам? Разве это не привело бы к тому же результату? Извините, я новичок в написании сценариев на c# и unity.
2. да, но с каждым из
if (Input.GetMouseButton(0) amp;amp; Input.GetKey(KeyCode.X)) { ...
соответственно. Это приведет к тому, что каждое преобразование игрового объекта будет перемещено соответственно каждым из входных данных3. Я попробовал твой метод. Я создал три сценария с конкретными входными данными в каждом сценарии и добавил их к каждому объекту, но результат тот же. Все объекты перемещаются независимо от того, что выбрано
4. убедитесь, что у вас нет подключенного предыдущего компонента или любого другого, выполняющего движение с помощью ввода
5. Я попробовал это. Это работает, если скрипт добавлен к одному объекту. В противном случае объекты тоже вращаются.