ch04游戏对象与图形基础

发布于:2022-10-31 ⋅ 阅读:(484) ⋅ 点赞:(0)


一、加载Fantasy Skybox FREE,构建自己的游戏场景

  • 主要是运用老师课件上讲的知识,包括Terrain内工具的使用
    在这里插入图片描述
  • 以及一些Unity基础知识,熟练掌握快捷键会更好
  • 这是我10分钟构建游戏场景的视频,视频五倍速链接: Unity制作游戏场景——5倍速

二、写一个简单的总结,总结游戏对象的使用

  1. 游戏对象:游戏中的一切东西都可以是游戏对象,游戏对象初始化带有必要的Tranformer组件,用来定位

  2. 创建GameObject

    • 通过编辑器GameObject可视化添加:可以直接拖拽到场景中或者添加在左侧栏
    • 脚本添加:Object.Instantiate()
  3. 获取GameObject

    • 在脚本中定义public变量,可以直接拖拽
    • 通过对象名字Find函数
    • 其他方法:(由于没有测试过,谨慎使用)
      • 通过标签获取单个游戏对象(FindWithTag方法)
      • 通过标签获取多个游戏对象(FindGameObjectsWithTags方法)
      • 通过类型获取单个游戏对象(FindObjectOfType方法)
      • 通过类型获取多个游戏对象(FindObjectsOfType方法)
  4. 为GameObject添加或者删除组件

    • 在Inspector中点击右上角的三个点可以手动添加删除
    • AddComponent<>()或者GetComponent<>()
  5. 发送广播和信息(查询资料得知:Message相关有3条指令)

    • SendMessage (“函数名”,参数,SendMessageOptions) //GameObject自身的Script
    • BroadcastMessage (“函数名”,参数,SendMessageOptions) //自身和子Object的Script
    • SendMessageUpwards (“函数名”,参数,SendMessageOptions) //自身和父Object的Script
  6. 克隆和预设

    • 将你设计好的GameObject拖到底栏(最好是perfabs文件夹中)可以得到你自己的预设
    • 将预设和其他GameObject一样拖出使用
    • 脚本:
      • 这里的"Perfabs/Ocean"是预设存储路径
      • typeof(GameObject))是类型
      • ocean_pos是预先定义好放置预设的位置
      • Quaternion.identity是预设的角度
 Ocean = Object.Instantiate(Resources.Load("Perfabs/Ocean", typeof(GameObject)), ocean_pos, Quaternion.identity, null) as GameObject;
  1. 运动、旋转和缩放

这些都可以通过快捷栏的工具可视化拖拽

  • 运动
    • 可视化直接修改物体的position
    • transform.Translate(Vector3)
    • transform.position += Vector3
  • 旋转
    • 自身:transform.Rotate()
    • 公转:transform.RotateAround()
  • 缩放:transform.localScale = Vector(x, y, z)
  1. 销毁GameObject
  • GameObject.Destroy
  • Destroy(gameObject);
  1. 更多操作参考: Unity3D官方中文手册

三、魔鬼与牧师 动作分离版

代码架构
这里实现了动作分离,PerfabsController实际上只是一个命名空间
在这里插入图片描述

  • MoveCharacter:
    • 里面控制了Preists和Devils的移动还有boat的移动,实际上都是从出发点到目的地的移动
    • 也控制了船的摇晃
public class MoveCharacter : MonoBehaviour
    {

        readonly float move_speed = 20;
        // 绕Z轴的摇摆的速度
        float z_Speed = 3.0f;
        // 绕X轴的摇摆的速度
        float x_Speed = 1.0f;

        int count = 0;

        int moving_status;  // 0->not moving, 1->moving to middle, 2->moving to dest
        Vector3 target;
        Vector3 middle;

        //移动
        void Update()
        {
            if(moving_status==1)
            {
           
                transform.position = Vector3.MoveTowards(transform.position, target , move_speed * Time.deltaTime);
            
                if (transform.position==target)moving_status = 0;
            }

           

            // 绕Z轴摇晃  
            if (this.transform.eulerAngles.z >= 4 && this.transform.eulerAngles.z <= 180)
            {
                z_Speed = -z_Speed;
            }
            else if (this.transform.eulerAngles.z <= (360 - 4) && this.transform.eulerAngles.z >= 180)
            {
                z_Speed = -z_Speed;
            }
            // 绕X轴摇晃  
            if (this.transform.eulerAngles.x >= 4 && this.transform.eulerAngles.x <= 180)
            {
                x_Speed = -x_Speed;
            }
            else if (this.transform.eulerAngles.x >= 180 && this.transform.eulerAngles.x <= (360 - 4))
            {
                x_Speed = -x_Speed;
            }
            this.transform.Rotate(z_Speed * Time.deltaTime, 0, z_Speed * Time.deltaTime);
       
        }
        public void setDestination(Vector3 _target)
        {
            target = _target;
            moving_status = 1;
           
        }

        public void setAngle()
        {
            moving_status = 3;
        }

        public void reset()
        {
            moving_status = 0;
        }
    }
}
  • 本次代码还更新了水的波浪,因为这个是伴随整个游戏的,所以没有加入Action当中,而是直接在GameObject内部更新
    public enum Superposition
    {
        //周期叠加
        Cycle,
        //振幅叠加
        Amplitude
    }

    public class WaterController
    {
        //水的位置
        readonly Vector3 ocean_pos = new Vector3(0, .4F, 0);

        //Ocean
        GameObject Ocean;

        //水波振幅
        public float amplitude = .7f;

        //波动的速度
        public float speed = 2.8f;

        //振幅叠加方式
        public Superposition superpositon = Superposition.Amplitude;

        //模型网格
        private Mesh sharedMesh;

        //网格初始顶点坐标数组
        private Vector3[] baseVertex;

        //网格修改后的顶点坐标数组(也就是每一次update之后)
        private Vector3[] nowVertex;


        public WaterController(string _name) 
        {   
            Ocean = Object.Instantiate(Resources.Load("Perfabs/Ocean", typeof(GameObject)), ocean_pos, Quaternion.identity, null) as GameObject;
            Ocean.name = "ocean";
            //初始化
            sharedMesh = Ocean.GetComponent<MeshFilter>().sharedMesh;
            baseVertex = sharedMesh.vertices;
            nowVertex = sharedMesh.vertices;
        }

        //GameObject的Update调用
        public void WaterWave()
        {
            //更新波浪顶点
            for (int i = 0; i < baseVertex.Length; i++)
            {
                nowVertex[i] = baseVertex[i];
                switch (superpositon)
                {
                    case Superposition.Cycle:
                        nowVertex[i].y += Mathf.Sin(Time.time * speed + baseVertex[i].x + baseVertex[i].z) * amplitude;
                        break;
                    case Superposition.Amplitude:
                        nowVertex[i].y += Mathf.Sin(Time.time * speed + baseVertex[i].x) * amplitude + Mathf.Sin(Time.time * speed + baseVertex[i].z) * amplitude;
                        break;


                }
            }

            sharedMesh.vertices = nowVertex;
        }

    }
  • 动作分离
    基类和继承动作基类
    public interface UserAction
    {
        void moveBoat();
        void PAndVIsClicked(PAndVController POrVCtrl);
        void restart();
    }

在这里插入图片描述

实现效果参考:Unity3D-牧师与魔鬼(升级版)
项目地址:项目地址