在 Unity 中围绕父对象旋转对象 [英] Rotate object around parent object in Unity

查看:127
本文介绍了在 Unity 中围绕父对象旋转对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Unity 的新手,正在尝试了解代码的工作原理,但我的简单项目遇到了问题.

I am new to unity and am trying to understand how the code works but am having a problem with my simple project.

我有一颗星星和一颗行星.行星是星星的孩子,就像这样:

I have a Star and a Planet. The planet is a child of the Star like so:

Star¬
   Planet

我向 Planet 添加了一个组件 C# 脚本,旨在使其围绕恒星旋转.但是当我按下播放键时,行星并没有移动.

I added a component C# script to Planet that is meant to make it rotate around the Star. But when i press play the planet is not moving.

这是我的脚本:

using UnityEngine;
using System.Collections;

public class Orbit : MonoBehaviour {

    public float rotateSpeed = 5.0f;
    public float orbitSpeed  = 1.0f;

    private Vector3 pos;

    void Start(){
        //get parent object position
        pos = transform.root.gameOject;
    }

    void Update() {
        // planet to spin on it's own axis
        transform.Rotate (transform.up * rotateSpeed * Time.deltaTime);

        // planet to travel along a path that rotates around the sun
        transform.RotateAround (pos, Vector3.up, orbitSpeed * Time.deltaTime);
    }
}

我不确定我的错误是什么.我希望有人可以提供帮助.

I am not sure what my mistake is. And am hoping some one can help.

附带问题,考虑到我最终想要拥有不止一个行星,为每个单独的行星旋转一个组件脚本是否有效,或者是否有更自动化的方法来执行此操作,例如在一个行星中迭代所有行星去吗?

Side question, given i want to eventually have more than one planet, is it efficient to have a component script for every individual planet to rotate or is there a more automative way to do it such as iterate through all the planets in one go?

单元版本 5.3.2f1

Unit Version 5.3.2f1

推荐答案

你应该考虑振荡.无论您使用 sin 还是 cos 都无所谓.你会得到相同的形状,但一个从 0 开始,因为 sin(0) = 0,另一个从 1 开始,因为 cos(0) = 1.

You should consider oscillation. Whether you use sin or cos does not really matter somehow. You will get the same shape but one will start at 0 as sin(0) = 0 and the other starts at 1 as cos(0) = 1.

sin 和 cos 的一个很好的特点是结果是 lerping 并被限制在 -1 和 1 之间.我们可以得到一个变量,它会不断地从 1 到 -1 再回到 1 等等.

One nice feature of sin and cos is that the result is lerping and clamped between -1 and 1. We can get a variable that will constantly go from 1 to -1 and back to 1 and so on.

以下完全基于基本三角学和单位圆

The following is entirely based on basic trigonometry and unit circle

void Update () 
{
        transform.localPosition= new Vector3(Mathf.Cos (Time.time ),0,Mathf.Sin (Time.time));
}

这是基于三角方程:

x = cos(2 * pi * k + t)
y = sin(2 * pi * k + t)

2 * PI * k 部分缩短为 Time.time,结果相同,如果您要重现真实情况,则只需要那些额外的精度.

The 2 * PI * k part is shorten to Time.time, result is the same, you would only need those for extra precision if you were to reproduce a real situation.

您想使用完整方程的其他情况是,如果您需要控制旋转所需的时间:

Other case you want to use the full equation is if you need to control the time it takes for a revolution:

 private float twoPi = Mathf.PI * 2f;
 void Update () 
{
        transform.localPosition= new Vector3(Mathf.Cos (twoPi * Time.time ),0,Mathf.Sin (twoPi * Time.time));
}

这将需要 1 秒才能完成完整的旋转.

This will take 1sec to do the full revolution.

当您对一个使用 Cos 时,您必须对另一个使用 Sin,否则您的对象将不会围绕父对象旋转.

When you use Cos for one, you have to use Sin for the other or your object will not spin around the parent.

您可以增加距离以将行星与恒星分开:

You can add distance to spread the planet apart from the star:

private float twoPi = Mathf.PI * 2f;
[SerializeField]private float amplitude = 2.0f;
void Update()
{
    float x = amplitude * Mathf.Cos (twoPi * Time.time );
    float z = amplitude * Mathf.Sin (twoPi * Time.time );
    transform.localPosition= new Vector3(x,0,z);
}

所有旋转的物品将以相同的频率 1 旋转,因此您应该能够为每个行星提供不同的频率:

All spinning items will rotate at the same frequency of 1 so you should be able to provide different frequencies to each planet:

private float twoPi = Mathf.PI * 2f;
[SerializeField]private float amplitude = 2.0f;
[SerializeField]private float frequency = 2.0f;
void Update()
{
    float x = amplitude * Mathf.Cos (twoPi * Time.time * frequency);
    float z = amplitude * Mathf.Sin (twoPi * Time.time * frequency);
    transform.localPosition= new Vector3(x,0,z);
}

如果在同一个物体内给 x 和 z 不同的频率,孩子将不会完全旋转,而是呈马蹄形.频率可以被同化为速度,因为它决定了完成一整圈的速度.

if you give different frequencies to x and z within the same object, the child will not spin entirely around but will have a horseshoe shape. Frequency could be assimilated to speed as it will define how fast one full revolution is performed.

然后您可以完全控制周期(这是速度的数学术语),一个周期是正弦曲线上两个峰值之间的时间(运动可以展平为正弦曲线,实际上是两个,x 和 z).频率与周期的关系是

You can then fully control the period (this is the math term for speed), a period is the time between two peaks on the sinusoidal (the movement can be flattened to a sinusoidal, two actually, x and z). The relation between frequency and period is

frequency = 1 / period;

所以频率越大,周期越短.如果您希望您的旋转需要 2 秒 => 频率 = 1/2 => 0.5.如果你需要 2 分钟,频率总是以秒为单位,所以 120 秒 => 频率 = 1/120 = 0.0083f;

So the greater the frequency, the shorter the period. If you want your revolution to take 2sec => frequency = 1 / 2 => 0.5. If you need 2 minutes, frequency is always in seconds so 120sec => frequency = 1 / 120 = 0.0083f;

您的所有行星都将在围绕恒星的同一位置旋转,即它们都将从左侧或右侧开始,因此您可以应用一个相位.这是来自初始方程的 k,它不是相乘而是相加:

All your planet will rotate at the same position around the star, that is they will all start from left or right so you can apply a phase. This is the k from the initial equation and it is not multiplied but added:

private float twoPi = Mathf.PI * 2f;
[SerializeField] private float amplitude = 2.0f;
[SerializeField] private float periodInSec = 120;
private float frequency = 2.0f;
[SerializeField] private float phase = 0.5f;

void Start()
{
    frequency = 1 / periodInSec;
}
void Update()
{
    float x = amplitude * Mathf.Cos (twoPi * Time.time * frequency + phase);
    float z = amplitude * Mathf.Sin (twoPi * Time.time * frequency + phase);
    transform.localPosition= new Vector3(x,0,z);
}

如果您需要提供椭圆形状(这是大多数 astres 的情况),您只需为 x 和 z 提供不同的幅度:

And if you need to provide an elliptic shape (which is the case of most astres), you simply give a different amplitude to x and z:

[SerializeField]private float amplitudeX = 2.0f;
[SerializeField]private float amplitudeZ = 3.0f;
[SerializeField] private float periodInSec = 120;
private float frequency = 2.0f;
[SerializeField] private float phase = 0.5f;
void Start()
{
    frequency = 1 / periodInSec;
}
void Update()
{
    float x = amplitudeX * Mathf.Cos (twoPi * Time.time * frequency + phase);
    float z = amplitudeZ * Mathf.Sin (twoPi * Time.time * frequency + phase);
    transform.localPosition= new Vector3(x,0,z);
}

如果您需要在一颗恒星周围有许多行星,并且您希望行星在所有三个轴上移动.也就是说,一个自旋平坦",而另一个自旋带自转,最简单的方法是使行星成为恒星孩子的孩子.

If you need to have many planets around one star and you want the planet to move on all three axis. That is, one spin "flat" while another one spin with a rotation, the easiest is to make the planet a child of a star child.

-Star
    -Container
        -Earth
    -Container
        -March

容器位于 (0,0,0) 处,您可以为每个容器设置不同的旋转角度,子行星将围绕恒星以自己的椭圆旋转.只要确保它们不会发生碰撞,数十亿人的生命就会受到威胁.

The containers are at (0,0,0) and you can give each container a different rotation and the child planet will rotate on its own ellipse around the star. Just make sure they don't collide, billions of lives at stake.

这篇关于在 Unity 中围绕父对象旋转对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆