Unity3d Note2

游戏对象运动的本质是什么?

游戏对象运动的本质就是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;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/happy990/article/details/79741948