简体   繁体   English

在Unity中围绕父对象旋转对象

[英]Rotate object around parent object in 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

I added a component C# script to Planet that is meant to make it rotate around the Star. 我向Planet添加了组件C#脚本,该脚本旨在使其绕Star旋转。 But when i press play the planet is not moving. 但是当我按下播放按钮时,行星并没有移动。

This is my script: 这是我的脚本:

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? 附带的问题是,鉴于我最终要拥有一个以上的行星,是否有一个使每个行星旋转的组件脚本有效,还是有一种更自动化的方式来做到这一点,例如一次遍历所有行星?

Unit Version 5.3.2f1 单元版本5.3.2f1

You should consider oscillation. 您应该考虑振荡。 Whether you use sin or cos does not really matter somehow. 无论您使用犯罪还是cos都不重要。 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. 您将获得相同的形状,但一个形状将从0开始,即sin(0)= 0,而另一个形状将从1开始,例如cos(0)= 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. sin和cos的一个很好的特征是结果在-1和1之间固定。我们可以得到一个变量,该变量将不断地从1变为-1,然后回到1,依此类推。

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));
}

this is based on the trig equation: 这基于trig方程:

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

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. 2 * PI * k部分缩短为Time.time,结果是相同的,如果要重现真实情况,则只需要额外的精度即可。

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));
}

This will take 1sec to do the full revolution. 完成整个旋转需要1秒。

When you use Cos for one, you have to use Sin for the other or your object will not spin around the parent. 当您将Cos用于其中之一时,必须将Sin用于另一方,否则您的对象将不会围绕父对象旋转。

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);
}

All spinning items will rotate at the same frequency of 1 so you should be able to provide different frequencies to each planet: 所有旋转的项目将以1的相同频率旋转,因此您应该能够为每个行星提供不同的频率:

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);
}

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. 如果在同一对象内给x和z赋予不同的频率,则该孩子不会完全旋转,而是呈马蹄形。 Frequency could be assimilated to speed as it will define how fast one full revolution is performed. 频率可以与速度同化,因为它将定义执行一整圈的速度。

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). 然后,您可以完全控制周期(这是速度的数学术语),周期是正弦曲线上两个峰值之间的时间(运动可以展平为正弦曲线,实际上是两个x和z)。 The relation between frequency and period is 频率和周期之间的关系是

frequency = 1 / period;

So the greater the frequency, the shorter the period. 因此,频率越高,周期越短。 If you want your revolution to take 2sec => frequency = 1 / 2 => 0.5. 如果您想旋转2秒=>频率= 1/2 => 0.5。 If you need 2 minutes, frequency is always in seconds so 120sec => frequency = 1 / 120 = 0.0083f; 如果需要2分钟,则频率总是以秒为单位,因此120秒=>频率= 1/120 = 0.0083f;

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: 这是初始方程式中的k,它不会相乘而是相加:

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);
}

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: 而且,如果需要提供椭圆形状(大多数astres就是这种情况),则只需为x和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

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. 容器位于(0,0,0),您可以为每个容器赋予不同的自转,子行星将绕着恒星以自己的椭圆形旋转。 Just make sure they don't collide, billions of lives at stake. 只要确保他们不会发生冲突,数十亿生命就危在旦夕。

public Vector3 pos and then Drag the Star in the Inspector. public Vector3 pos ,然后将其public Vector3 pos检查器中。 much easier. 容易得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM