【Unity3d学习】空间与物体运动——制作简单太阳系

写在前面

关于游戏对象运动的另一个编程实验“魔鬼与牧师”

见我的Github:传送门
博客地址:传送门

了解游戏对象运动的本质

首先通过初步学习,可以了解到我们在Unity中创建的物体,都会带有Transfrom的部件,其中包含了PositionRotationScale三个主要部分。而实际上物体的运动就是改变这三个状态,使其能够平移、旋转、缩放,以及这三种运动的组合。构成游戏对象所有运动的基础。还有一种理解,就是通过矩阵变换,使得物体空间属性发生变化,这就是对象运动的本质。

实现物体简单运动

用三种不同方法,实现物体的抛物线运动

  1. 使用改变position方法,直接将position加上一个三维向量,得到的就是一个新的position。其中模拟的是抛物线运动,在y轴有一个加速度,所以用了 s = v 0 t + 1 2 a t 2 s=v_0t + \frac{1}{2}at^2 s=v0t+21at2的公式计算每一步长移动的距离,由于是向下运动,所以要加上负号。由于我们计算的是每一小段时间内的物体位移的增量,所以要记录每一个时段开始(也就是上一个时段结束时)物体的初速度 v 2 v_2 v2
public class Parabolic : MonoBehaviour
{
    // Start is called before the first frame update
    public float v = 0.5f;
    public float v2 = 0;
    const float a = 9.8f;
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        this.transform.position += new Vector3(v*Time.deltaTime, (float)(-v2*Time.deltaTime-0.5*g*(Time.deltaTime)*(Time.deltaTime)), 0);
        v2 += g * Time.deltaTime;
    }
}
  1. 使用transform的Translate方法(由于代码大体相同,所以只写出关键部分,即使用函数不同)
void Update()
{
	this.transform.Translate(new Vector3(v*Time.deltaTime, (float)(-v2*Time.deltaTime-0.5*g*(Time.deltaTime)*(Time.deltaTime)), 0));
	v2 += g * Time.deltaTime;
}

3.使用 SetPositionAndRotation函数
使用此函数就需要计算得到物体最后时刻的位置,而不能简单的相加。由于我们设置物体y方向上初速度为0,所以运动的总距离就是 y 0 − 1 2 a t 2 y_0-\frac{1}{2}at^2 y021at2
先保存原来的y坐标为 y 0 y_0 y0,在这个基础上,在y方向作匀加速运动,再计算出坐标。而总时间的话要累积加上每次Update的时间。

void Update()
    {   
        this.transform.SetPositionAndRotation(new Vector3(v*t, origin_y - (float)(0.5*g*t*t), 10), this.transform.rotation);
        t += Time.deltaTime;
    }

简单太阳系制作

首先创建一堆球体,按照一定的比例改变他们的大小,并且给它们重命名。(这里没有使用真实比例,只是粗略的体现哪个行星比较大,因为按照真实比例的话,有的行星可能在场景中小得看不见了),然后将它们拖到太阳对象中,作为子物体:
在这里插入图片描述
调整它们的相对位置,使其距离太阳的轨道距离不同。
然后到网上寻找各个行星的贴图,并且把他们拖到对应的球体上,形成材料。
在这里插入图片描述
在这里插入图片描述
成品如下:
在这里插入图片描述
然后每个球体都可以绕太阳旋转,所以编写一个简单脚本,让其绕太阳运动。
这里用到的是老师上课讲到的Quaternion以及欧拉角的应用,根据旋转角度以及旋转轴来改变物体的位置。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rotate : MonoBehaviour
{
    public int speed = 10;
    public Vector3 e;
    float ry, rx;
    // Start is called before the first frame update
    void Start()
    {
        // 随机生成法向量,使x尽可能小于y,即旋转轴基于y轴偏一点点
        rx = Random.Range(1,5);
        ry = Random.Range(10, 30);
        e = new Vector3(rx, ry, 0);
    }
    // Update is called once per frame
    void Update()
    {
        // 按照一定速度,生成旋转变换的四元组(类似矩阵变换)
        Quaternion q = Quaternion.AngleAxis(speed * Time.deltaTime, e);
        // 由于是太阳的子物体,所以可以指改变相对位置即可,防止太阳不在原点
        // 也可以通过相对坐标和绝对坐标的转换,不过比较麻烦
        this.transform.localPosition = q * this.transform.localPosition;
    }
}

将脚本拖到每个球体的部件中,更改相应的速度参数:
在这里插入图片描述
这样就基本实现了旋转运动。(对于月亮与地球关系也是一样,由于月亮也是地球的子物体,所以不需要特别更改)

一点美化

将摄像头(Camera)的Clear Flag改成solid color,然后把背景颜色改为黑色或者比较深的颜色(当然也可以使用Skybox,只要有合适的素材),这样游戏场景看上去就比较像星空的黑色(尽管只有几个球)。
在这里插入图片描述
除了场景中的平行光之外,还可以增加太阳本身的光源,在太阳的Inseptor里增加,Light部件,调整为点光源,并且设置颜色以及强度(Intensity):
在这里插入图片描述
这样得到的效果就是行星面向太阳的一面为比较亮,但是由于场景中有平行光的存在,另一面又不至于全暗,看起来比较适合。效果如下:
在这里插入图片描述
然后为了证明行星转动轨迹不在同一个法平面上,我们可以添加轨迹来观察,给每个行星Inseptor中添加Trail Renderer,调整宽度不要太大,还能改变轨道颜色,不过好像不能通过Color来改变,只能通过material来改变颜色。还有轨道记录时间(Time)尽可能调大,让行星轨迹能够绕一周。设置如下:
在这里插入图片描述

完成之后就可以开始测试,效果如下:
在这里插入图片描述
动态如下:
在这里插入图片描述

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值