3D游戏编程与设计3——空间与运动

本文探讨了游戏对象运动的本质,通过修改Transform属性实现抛物线运动,并详细介绍了三种方法的具体实现。此外,还提供了使用Unity实现完整太阳系模型的代码示例,包括各行星的公转和自转。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、简答并用程序验证

  • 游戏对象运动的本质是什么?
    游戏对象运动的本质是游戏对象的空间属性的改变,包括游戏对象 Transform 属性中 Position 和 Rotation 属性的改变。
public class ExampleClass : MonoBehaviour
{
    void Update()
    {
        this.transform.position += Vector3.left * Time.deltaTime;
    }
}
  • 请用三种以上方法,实现物体的抛物线运动。(如,修改 Transform 属性,使用向量 Vector3 的方法…)
    假设该物体的抛物线运动是 x 轴正方向速度保持不变,y 轴负方向保持一定加速度的运动。

① 第一种方法是通过修改 Transform 属性来实现抛物线运动。 代码如下:

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

public class parabolaBehavior1 : MonoBehaviour
{
    private float xSpeed = 5f;
    private float ySpeed = 0;
    private float gravity = 9.8f;

    void Start()
    {
        Debug.Log("start!");
    }

    void Update()
    {
        this.transform.position += Vector3.right * Time.deltaTime * xSpeed;
        this.transform.position += Vector3.down * Time.deltaTime * ySpeed;
        ySpeed += gravity * Time.deltaTime;
    }
}

② 第二种方法是通过使用向量 Vector3 的方法来实现抛物线运动。代码如下:

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

public class parabolaBehavior2 : MonoBehaviour
{
    private float xSpeed = 5f;
    private float ySpeed = 0;
    private float gravity = 9.8f;

    void Start()
    {
        Debug.Log("start!");
    }

    void Update()
    {
        Vector3 trans = new Vector3(xSpeed * Time.deltaTime, -ySpeed * Time.deltaTime, 0);
        this.transform.position += trans;
        ySpeed += gravity * Time.deltaTime;
    }
}

③ 第三种方法是通过使用 Translate 方法来实现抛物线运动。代码如下:

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

public class parabolaBehavior3 : MonoBehaviour
{
    private float xSpeed = 5f;
    private float ySpeed = 0;
    private float gravity = 9.8f;

    void Start()
    {
        Debug.Log("start!");
    }

    void Update()
    {
        Vector3 trans = new Vector3(xSpeed * Time.deltaTime, -ySpeed * Time.deltaTime, 0);
        this.transform.Translate(trans);
        ySpeed += gravity * Time.deltaTime;
    }
}
  • 写一个程序,实现一个完整的太阳系,其他星球围绕太阳的转速必须不一样,且不在一个法平面上。

① 首先在场景中创建一个太阳、八个行星和一个月亮,八大行星距离太阳由进到远分别为水星、金星、地球、火星、木星、土星、天王星和海王星。将下载好的贴图拖入球体,分别设置好每个球体的大小和位置,将太阳作为八大行星的父类,地球作为月亮的父类。制作太阳系预制。
在这里插入图片描述
在这里插入图片描述
② 编写脚本,让八大行星围绕太阳的转速不一样,且不在一个法平面上。
使用 Transform 对象的 RotateAround 方法,第一个参数是围绕的旋转点即太阳的位置,第二个参数是旋转的法向量,使用随机的 y 和 z,制造不同的运动法平面,第三个参数是旋转的速度,实现公转。
使用 Transform 对象的 Rotation 方法,参数是旋转的速度,实现球体的自转。
将写好的脚本挂到 Sun 上,并将对应对象拖到 Script 中的 Transform 对象中。
在这里插入图片描述
实现代码如下:

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

public class Rotate : MonoBehaviour
{
    public Transform sun;
    public Transform mercury;
    public Transform venus;
    public Transform earth;
    public Transform mars;
    public Transform jupiter;
    public Transform saturn;
    public Transform uranus;
    public Transform neptune;
    public Transform moon;

    Vector3[] a = new Vector3[9];
    float y, z;

    // Start is called before the first frame update
    void Start()
    {
        sun.position = Vector3.zero;
        for(int i = 0; i < 9; i++)
        {
            y = Random.Range(1, 360);
            z = Random.Range(1, 360);
            a[i] = new Vector3(0, y, z);
        }
    }

    // Update is called once per frame
    void Update()
    {
        mercury.RotateAround(sun.position, a[0], 47 * Time.deltaTime);
        mercury.Rotate(Vector3.up * 47 * Time.deltaTime);

        venus.RotateAround(sun.position, a[1], 35 * Time.deltaTime);
        venus.Rotate(Vector3.up * 35 * Time.deltaTime);

        earth.RotateAround(sun.position, a[2], 30 * Time.deltaTime);
        earth.Rotate(Vector3.up * 30 * Time.deltaTime);

        mars.RotateAround(sun.position, a[3], 24 * Time.deltaTime);
        mars.Rotate(Vector3.up * 24 * Time.deltaTime);

        jupiter.RotateAround(sun.position, a[4], 13 * Time.deltaTime);
        jupiter.Rotate(Vector3.up * 13 * Time.deltaTime);

        saturn.RotateAround(sun.position, a[5], 11 * Time.deltaTime);
        saturn.Rotate(Vector3.up * 11 * Time.deltaTime);

        uranus.RotateAround(sun.position, a[6], 9 * Time.deltaTime);
        uranus.Rotate(Vector3.up * 9 * Time.deltaTime);

        neptune.RotateAround(sun.position, a[7], 8 * Time.deltaTime);
        neptune.Rotate(Vector3.up * 8 * Time.deltaTime);

        moon.RotateAround(earth.position, Vector3.right, Time.deltaTime * 400);
    }
}

③ 给八大行星添加足迹组件 Trail Render,记录行星移动轨迹。
在这里插入图片描述
在太阳上添加一个点光源。
在这里插入图片描述
运行结果如图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、编程实践

  • 阅读以下游戏脚本

Priests and Devils 牧师和魔鬼
Priests and Devils is a puzzle game in which you will help the Priests and Devils to cross the river within the time limit. There are 3 priests and 3 devils at one side of the river. They all want to get to the other side of this river, but there is only one boat and this boat can only carry two persons each time. And there must be one person steering the boat from one side to the other side. In the flash game, you can click on them to move them and click the go button to move the boat to the other direction. If the priests are out numbered by the devils on either side of the river, they get killed and the game is over. You can try it in many > ways. Keep all priests alive! Good luck!
《牧师和魔鬼》是一款益智游戏,玩家可以在限定的时间内帮助牧师和魔鬼过河。在河的一边有三个牧师和三个魔鬼。他们都想去这条河的另一边,但是只有一条船,而且这条船每次只能载两个人。一定有一个人把船从一边开到另一边。在游戏中,你可以点击对象来移动它们,然后点击go按钮将船移动到另一个方向。如果牧师被河两岸的魔鬼所杀,游戏也就结束了。你可以用很多方式来尝试。让所有的牧师都活着!

程序需要满足的要求:

  • play the game( http://www.flash-game.net/game/2535/priests-and-devils.html )
  • 列出游戏中提及的事物(Objects)
  • 用表格列出玩家动作表(规则表),注意,动作越少越好
  • 请将游戏中对象做成预制
  • 在 GenGameObjects 中创建 长方形、正方形、球 及其色彩代表游戏中的对象。
  • 使用 C# 集合类型 有效组织对象
  • 整个游戏仅 主摄像机 和 一个 Empty 对象, 其他对象必须代码动态生成!!! 。 整个游戏不许出现 Find 游戏对象, SendMessage 这类突破程序结构的 通讯耦合 语句。 违背本条准则,不给分
  • 请使用课件架构图编程,不接受非 MVC 结构程序
  • 注意细节,例如:船未靠岸,牧师与魔鬼上下船运动中,均不能接受用户事件!

游戏中提及的事物(Objects):
游戏对象:3牧师、3魔鬼
场景:2陆地、河、船

玩家动作表(规则表):

玩家动作条件
开船船在开始岸、船在结束岸、船上有人
开始岸牧师上船船在开始岸,船有空位,开始岸有牧师
开始岸魔鬼上船船在开始岸,船有空位,开始岸有魔鬼
结束岸牧师上船船在结束岸,船有空位,结束岸有牧师
结束岸魔鬼上船船在结束岸,船有空位,结束岸有魔鬼

将游戏中对象做成预制:
在这里插入图片描述
整个游戏仅 主摄像机 和 一个 Empty 对象, 其他对象由代码动态生成:
在这里插入图片描述
使用 MVC 架构。Model 是场景中所有的游戏对象,View 是 UserGUI 提供用户交互,Controller 是 FirstController 和 Director。

游戏初始界面如图:
在这里插入图片描述
游戏失败界面如图:
在这里插入图片描述
在这里插入图片描述
游戏获胜界面如图:
在这里插入图片描述
游戏代码如下:
boatBehavior.cs

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

public class boatBehavior : MonoBehaviour
{

    public boatAction action;

    // Use this for initialization
    void Start()
    {
        action = SSDirector.getInstance().currentSceneController as boatAction;
    }

    private void OnMouseDown()
    {
        action.boat_move(this.gameObject);
    }

    // Update is called once per frame
    void Update()
    {

    }
}

priestBehavior.cs

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

public class priestBehavior : MonoBehaviour
{

    private priestAction action;

    // Use this for initialization
    void Start()
    {
        action = SSDirector.getInstance().currentSceneController as priestAction;
    }

    private void OnMouseDown()
    {
        action.priest_move(this.gameObject);
    }

    // Update is called once per frame
    void Update()
    {

    }
}

devilBehavior.cs

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

public class devilBehavior : MonoBehaviour
{

    private devilAction action;

    // Use this for initialization
    void Start()
    {
        action = SSDirector.getInstance().currentSceneController as devilAction;
    }

    private void OnMouseDown()
    {
        action.devil_move(this.gameObject);
    }

    // Update is called once per frame
    void Update()
    {

    }
}

UserGUI.cs

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

public class UserGUI : MonoBehaviour
{

    private IUserAction action;

    // Use this for initialization
    void Start()
    {
        action = SSDirector.getInstance().currentSceneController as IUserAction;
    }

    void onGUI()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}

Interface.cs

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

public interface IsceneController
{
    void LoadResources();
    void Restart();
}

public interface IUserAction
{


}

public interface devilAction
{
    void devil_move(GameObject obj);
}

public interface priestAction
{
    void priest_move(GameObject obj);
}

public interface boatAction
{
    void boat_move(GameObject obj);
}

Director.cs

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

public class SSDirector : System.Object
{

    // singlton instance
    private static SSDirector _instance;

    public IsceneController currentSceneController { get; set; }
    public bool running { get; set; }

    //get instance anytime anywhere!
    public static SSDirector getInstance()
    {
        if (_instance == null)
        {
            _instance = new SSDirector();
        }
        return _instance;
    }

    public int getFPS()
    {
        return Application.targetFrameRate;
    }

    public void setFPS(int fps)
    {
        Application.targetFrameRate = fps;
    }
}

FirstController.cs

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

public class SSDirector : System.Object
{

    // singlton instance
    private static SSDirector _instance;

    public IsceneController currentSceneController { get; set; }
    public bool running { get; set; }

    //get instance anytime anywhere!
    public static SSDirector getInstance()
    {
        if (_instance == null)
        {
            _instance = new SSDirector();
        }
        return _instance;
    }

    public int getFPS()
    {
        return Application.targetFrameRate;
    }

    public void setFPS(int fps)
    {
        Application.targetFrameRate = fps;
    }
}

视频链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值