Unity空间与运动
3D游戏设计第三次作业
前言
这是中山大学2020年3D游戏设计的第三次作业,如有错误,请指正,感谢您的阅读。
简答并用程序验证
游戏对象运动的本质是什么?
- 游戏对象运动的本质是游戏对象的属性随每一帧的而发生的改变。改变主要为绝对或者相对位置的改变和是所处位置的角度的旋转变化。
请用三种方法以上方法,实现物体的抛物线运动。(如,修改Transform属性,使用向量Vector3的方法…)
- 利用修改transform的position属性,让物体有一个向上的初始速度以及一个向下的加速度,和一个匀速向右的运动,叠加后即为抛物线运动。代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class m1 : MonoBehaviour
{
private float speed=-8.0f;
// Update is called once per frame
void Update()
{
this.transform.position += Vector3.down * Time.deltaTime * speed;
this.transform.position += Vector3.right * Time.deltaTime * 3;
speed += 0.1f;
}
}
- 直接声明创建一个Vector3变量,同时定义该变量的值,也是竖直方向上有一个向下的加速度,水平方向是一个保持不变的数值,然后将游戏对象原本的position属性与该向量相加即可实现抛物线。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class m2 : MonoBehaviour
{
private float speed = 8f;
// Update is called once per frame
void Update()
{
Vector3 change = new Vector3(Time.deltaTime * 3, Time.deltaTime * speed, 0);
this.transform.position += change;
speed-=0.1f;
}
}
- 利用重力加速度,只需要赋值一个初始速度即可。在unity中,我们可以给物体赋予物理属性,即它可以有质量大小等具体的概念,这个物体一旦有了重量,就会收到重力影响,具体操作方法如下:
选中这个球,然后再component中选择physics中的rigidbody(刚体),如下
这样,在sphere的设置中就有关于rigid body的参数设置,我们勾选use gravity选项。
下面,编写脚本赋予物体初始速度。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class m3 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
this.GetComponent<Rigidbody>().velocity = new Vector3(5, 8, 0);
}
}
- 利用transform中的translate函数来进行改变position,与第二种方法很类似,只是使用了函数代替了赋值操作。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class m4 : MonoBehaviour
{
private float speed = 8f;
// Update is called once per frame
void Update()
{
Vector3 change = new Vector3(Time.deltaTime * 3, Time.deltaTime * speed, 0);
transform.Translate(change);
speed -= 0.1f;
}
}
生成的效果图如下所示:
写一个程序,实现一个完整的太阳系, 其他星球围绕太阳的转速必须不一样,且不在一个法平面上。
太阳系其实与上课做地月系大同小异,但为了更加美观,在太阳系中添加了一些后期,但整体过程还是没有太大变化的。
成品
为了观看的更加清晰,gif中手动调制了镜头。下面,就详细讲解以下如何完成一个太阳系吧。
自转与公转
第一步,我们首先来编写脚本,因为脚本可以在一会设置对象的时候直接进行参数设置,会省去很多不必要的步骤。
自转
自转代码只需要考虑绕自己中轴旋转即可。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class rotation : MonoBehaviour
{
public float speed;
// Update is called once per frame
void Update()
{
transform.Rotate(new Vector3(0, 1, 0), speed * Time.deltaTime);
}
}
公转
公转的话需要考虑法平面偏移以及速度和绕谁旋转三个参数,利用函数RotateAround即可完成。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class revolution : MonoBehaviour
{
public int offset_x;//法平面的偏移角x
public int offset_y;//法平面的偏移角y
public float speed;
public Transform target;
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.RotateAround(target.position, new Vector3(offset_x, offset_y, 0), speed * Time.deltaTime);
}
}
添加球体
添加球体之前,我们将Main Camera中的Camera.
background调为纯黑色(宇宙就是纯黑的嘛)。
下面添加球体,先添加一个太阳,使用复制粘贴创建共9个球,将每个星球的贴图拖放到该对象上。根据星球大小调好合适的scale(建议使用transform中的scale直接调参数),并将两个脚本拖到对象上(太阳只有自转),按下表设置自转公转,并且将偏移角设为1-3之间的两个数的排列组合。下面给出各个星球自转公转和大小的的信息。
星球 | 公转 | 自转 | 大小 |
---|---|---|---|
水星Mercury | 87.9 | 58.6 | 8 |
金星Venus | 224.7 | 243 | 6 |
地球Earth | 1 | 1 | 5 |
火星Mars | 1.9 | 1 | 7 |
木星Jupiter | 11.8 | 1 | 1 |
土星Saturn | 29.5 | 2 | 2 |
天王星Uranus | 84 | 4 | 4 |
海王星Neptune | 164.8 | 3 | 3 |
设置好这些,太阳系就已经可以初步正常运行了。
添加月球
我们再添加一个球体作为地球的子对象,同样缩小到合适的比例后放在地球与火星之间(更靠近地球一些)。然后,编写代码。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class smallPlanet : MonoBehaviour
{
public float speed;
// Update is called once per frame
void Update()
{
Vector3 position = this.transform.parent.position;
this.transform.RotateAround(position, Vector3.up, speed * Time.deltaTime);
}
}
将脚本添加到月球后,同样需要添加自转脚本,设置好两个速度,运行就会发现月球绕地球旋转。
添加轨迹
现在,我们无法看出每个行星轨迹。故我们添加一个轨迹来更好的研究其轨迹。
多选选中除了太阳之外所有的球体,然后add component中添加trail renderer。
将width调为0.1,time调为100,materials中的element 0调为默认(default开头),如下图所示。
这样,行星的运动轨迹就可以看的一清二楚啦!
太阳光
太阳光是最复杂的设计,我们需要使用后期软件来实现。首先添加一个网上搜来的太阳shader文件(文末有项目的详细地址,需要可以自取资源Assets/Sun),将其制作为material,然后把material拖到太阳上,重新设置太阳的图案,如下所示:
太阳比以前亮了很多,但是还不会发光?
这就需要后期处理了,首先我们要确保自己的项目中有后期处理的包(后期处理包),将该包拖入项目目录下的Packages文件夹下即可自动完成加载和安装。
然后,新建一个对象,命名为PostProcess,将其Layer修改为Post-Process(如果没有就直接add新的Layer)。
修改Main Camera,添加Post-process Layer设置,并配置如下所示:
返回到刚刚创建的PostProcess中,先在Assets文件夹下新建一个后期处理文件,如下图
新建完成后,在PostProcess中添加新的设置Post-process Volume,并且通过add effect添加Bloom,完成以下配置
你会惊奇的发现,太阳有光发出了,到此,本项目也就完成了。
代码仓库
编程实践
为控制博客长度,请移步:魔鬼与牧师
思考题
- 使用向量与变换,实现并扩展 Tranform 提供的方法,如 Rotate、RotateAround 等
首先介绍一个函数`Quaternion.AngleAxis
Description描述
Creates a rotation which rotates angle degrees around axis.
绕axis轴旋转angle,创建一个旋转。
所以,void Rotate(Transform t, Vector3 axis, float angle)
函数就可以用该函数写成
void Rotate(Transform t, Vector3 axis, float angle)
{
var rotate = Quaternion.AngleAxis(angle, axis);//计算旋转
t.position *= rotate;//位置旋转
t.rotation *= rotate;//角度旋转
}
而RotateAround(Transform t, Vector3 center, Vector3 axis, float angle)
也可以写成:
void RotateAround(Transform t, Vector3 center, Vector3 axis, float angle)
{
var rotate = Quaternion.AngleAxis(angle, axis);
var direction = position - center;//计算位移向量
direction *= rotate;//位移向量旋转
t.position = center + direction;//计算当前位置
t.rotation *= rotate;//计算旋转
}