Unity3d Note2
程序员文章站
2024-01-24 20:02:52
...
游戏对象运动的本质是什么?
游戏对象运动的本质就是transform属性坐标的连续改变
我们想让位置随时间连续变化,而update()函数是每帧被调用一次,而帧率在不断变化,Update()被调用的时间并不是线性的,所以需要乘以帧间时间,也就是Time.DeltaTime。
void Update () {
this.transform.position += Vector3.left * Time.deltaTime;
}
用三种以上方法,实现物体的抛物线运动
使用transform.position方法
public float speed = 1.0f;
void Update () {
speed += 0.1f;
this.transform.position += speed * Vector3.up * Time.deltaTime;
this.transform.position += Vector3.left * Time.deltaTime;
}
使用transform.translate()方法
public float speed = 1.0f;
void Update()
{
speed += 0.05f;
transform.Translate(speed * Vector3.up * Time.deltaTime);
transform.Translate(Vector3.left * Time.deltaTime);
}
使用Vector3.MoveTowards()方法
float t = 0.0f;
void Start()
{
transform.position = new Vector3(0.0f, 0.0f, 0.0f);
}
void FixedUpdate()
{
t += Time.fixedDeltaTime;
transform.position = Vector3.MoveTowards(transform.position, new Vector3(t, t * t, 0), Time.fixedDeltaTime);
}
通过添加刚体属性,并设置恒力和速度
public float speed = 1.0f;
public Rigidbody rb;
void FixedUpdate()
{
rb.velocity = new Vector3(1f, 0, 0);
rb.AddForce(0, speed, 0, ForceMode.Impulse);
}
写一个程序,实现一个完整的太阳系, 其他星球围绕太阳的转速必须不一样,且不在一个法平面上
transform.RotateAround()的第一个参数指定围绕旋转的坐标点,第二个参数表示围绕旋转的法向量,第三个参数表示旋转的速度。由于我们要围绕太阳旋转,所以第一个参数设为太阳的坐标,也就是原点,第二个参数和第三个都使用随机生成的数值。然后把这个脚本挂载到行星上,就可以旋转了。
public class NewBehaviourScript : MonoBehaviour {
public float speed;
float rz, rx, ry;
// Use this for initialization
void Start()
{
speed = Random.Range(10, 40);
rx = Random.Range(0, 20);
ry = Random.Range(0, 20);
rz = Random.Range(0, 20);
}
// Update is called once per frame
void Update()
{
Vector3 axis = new Vector3(0, ry, rz);
this.transform.RotateAround(new Vector3(0, 0, 0), axis, speed * Time.deltaTime);
}
}
将月球设为地球的子对象,然后讲上面的脚本的太阳坐标改为地球的,就可以使月球围绕地球旋转。
public class NewBehaviourScript1 : MonoBehaviour {
public Transform origin;
public float speed;
float rz, rx, ry;
// Use this for initialization
void Start()
{
speed = Random.Range(10, 40);
rx = Random.Range(0, 20);
ry = Random.Range(0, 20);
rz = Random.Range(0, 20);
}
// Update is called once per frame
void Update()
{
Vector3 axis = new Vector3(0, ry, rz);
this.transform.RotateAround(origin.position, axis, speed * Time.deltaTime);
}
}
设置地球自转,将围绕旋转设为自己的坐标,并调整一下旋转法向量和速度即可。
public class NewBehaviourScript2 : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
this.transform.RotateAround(this.transform.position, Vector3.up, 2);
}
}
效果图
牧师与恶魔
效果图
游戏中提及的事务
玩家动作表
- 点击牧师
- 点击恶魔
- 点击船只
- 点击重新开始按钮
主要参考博客https://www.jianshu.com/p/07028b3da573实现
添加了一些拓展功能
- 开始按钮Start
- 计时功能Time Left
- 游戏开始之前和失败以后不能再响应用户点击的事件,用户只能点击Start和Restart
修改代码,在UserAction接口中添加属性 bool IsStop 来判断是否响应用户事件
修改UserGUI
private float time = 0;
private bool isIni=false;
void Update()
{
if (!action.IsStop)
time += Time.deltaTime;
}
void OnGUI()
{
if (isIni == false)
{
if (GUI.Button(new Rect(Screen.width / 2 - 70, Screen.height / 2, 140, 70), "Start", buttonStyle))
{
action.IsStop = false;
isIni = true;
}
}
GUI.Label(new Rect(Screen.width - 100, 0, 100, 50), "Time Left:" + Mathf.RoundToInt(60 - time));
if (Mathf.RoundToInt(time) == 60)
{
action.IsStop = true;
GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 85, 100, 50), "Timeout!", style);
if (GUI.Button(new Rect(Screen.width / 2 - 70, Screen.height / 2, 140, 70), "Restart", buttonStyle))
{
time = 0;
action.IsStop = false;
status = 0;
action.restart();
}
return;
}
if (status == 1)
{
action.IsStop = true;
GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 85, 100, 50), "Gameover!", style);
if (GUI.Button(new Rect(Screen.width / 2 - 70, Screen.height / 2, 140, 70), "Restart", buttonStyle))
{
status = 0;
action.restart();
time = 0;
}
}
else if (status == 2)
{
action.IsStop = true;
GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 85, 100, 50), "You win!", style);
if (GUI.Button(new Rect(Screen.width / 2 - 70, Screen.height / 2, 140, 70), "Restart", buttonStyle))
{
status = 0;
action.restart();
time = 0;
}
}
}