3D游戏编程 作业四 天空盒与牧魔结构升级

前言

实验题跟效果跟上次一样,这次只放脚本

github: 纯脚本


一、天空盒构建场景

1. 布置天空

在assets中创建一个material,命名为mySky,将它的Shader改为Skybox/6 Sided,在Fantasy Skybox中找到对应front, back, left, right, up, down六张图导入
在这里插入图片描述
其中,可以通过改变Tint Color来改变天空颜色;exposure是来调整天空的曝光度的,可以改变其亮度;rotation不用说了,选择整个天空
在这里插入图片描述

这里copy一下学长博客的理解
天空盒是一个全景视图,分为六个纹理,表示沿主轴(上,下,左,右,前,后)可见的六个方向的视图。如果天空盒被正确的生成,纹理图像会在边缘无缝地拼接在一起,可以在内部的任何方向看到周围连续的图像。全景图片会被渲染在场景中的所有其他物体后面,并旋转以匹配相机的当前方向(它不会随着相机的位置而变化,而照相机的位置总是位于全景图的中心)。因此,天空盒子是在图形硬件上以最小负载向场景添加现实性的简单方式。

2.创建地形

选择菜单栏中的GameObject->3D Object->Terrain,建立一块地,然后可以用unity提供的地形设计工具来改变这块地的地形和贴图。
最上面一行是unity提供的简单工具,从左到右依次是:创建相邻地块、绘制地形、种树、种草和设置。
在这里插入图片描述
而在绘制地形中又有多种选项,分别是:
升高或降低地形、绘制洞、绘制纹理、设置高度、平滑高度、绘制有特定地质特征的纹理。
在这里插入图片描述
一般是左键上升,右键下降。其中Brush Size控制面积,Opacity控制高度

3.完成地形绘制

在这里插入图片描述
免费天空盒没有草跟树,这里我就不下载资源,直接随便画了一个地形

二、游戏对象简单总结

在unity中,有很多种游戏对象,包括空对象、3D游戏对象、2D游戏对象、事件、灯光、声音、视频、UI界面、摄像机等。其中我们最常用的就是3D游戏对象、灯光、声音、UI界面和摄像机。
在这里插入图片描述

游戏对象是游戏中人物、道具、场景等对象的总称,它们有基础的属性,但没有具体的独特的功能,用于容纳不同的组件。只有挂载了组件后,一个游戏对象才有了属于它的功能。

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

1.结构图

在这里插入图片描述
这里单独把动作拎出来,额外开创了一堆类,用于调整与控制

裁判类

    public class Judge : MonoBehaviour//裁判类
    {
        public int Check(LandModel start_land,LandModel end_land,BoatModel boat)
        {
            int start_priest = (start_land.GetRoleNum())[0];
            int start_devil = (start_land.GetRoleNum())[1];
            int end_priest = (end_land.GetRoleNum())[0];
            int end_devil = (end_land.GetRoleNum())[1];

            if (end_priest + end_devil == 6)return 2;     //获胜

            int[] boat_role_num = boat.GetRoleNumber();
            if (boat.GetBoatSign() == 1)         //在开始岸和船上的角色
            {
                start_priest += boat_role_num[0];
                start_devil += boat_role_num[1];
            }
            else                                  //在结束岸和船上的角色
            {
                end_priest += boat_role_num[0];
                end_devil += boat_role_num[1];
            }
            if (start_priest > 0 && start_priest < start_devil) //失败
            {      
                return 1;
            }
            if (end_priest > 0 && end_priest < end_devil)        //失败
            {
                return 1;
            }
            return 0;
        }
    }
    

行动类

由于我在上次作业中已经把行动抽象成一个类,而且三个行动有较大的分割,懒得很难组合成框架,所以我这里只展示框架模板,强行塞进去的行动代码不管。跟上次一样,这些东西都放在model中。


    public enum SSActionEventType : int { Started, Complete }
    public interface ISSActionCallback	{   
		void SSActionEvent(SSAction source,
		SSActionEventType events = SSActionEventType.Complete,
        int intParam = 0, 
        string strParam = null, 
        Object objectParam = null);
	}
    public class SSAction : ScriptableObject
    {

        public bool enable = true;
        public bool destroy = false;

        public GameObject GameObject { get; set; }
        public Transform Transform { get; set; }
        public ISSActionCallback Callback { get; set; }

        protected SSAction() { }

        // Use this for initialization
        public virtual void Start()
        {
            throw new System.NotImplementedException();
        }

        // Update is called once per frame
        public virtual void Update()
        {
            throw new System.NotImplementedException();
        }
    }

    public class SSMoveToAction : SSAction{
        int move_sign = 0;                        //0是不动,1z轴移动,2x轴移动
        float rotaspeed = 200.0f; //转向速度
        float mspeed = 5;//移动速度

        Transform maincamera;
        int kind = 0;//移动方式

        Vector3 mid_position;//中间的位置
        Vector3 end_position;//最终的位置

        Quaternion mid_qua;//移动向中间的朝向

        Quaternion end_qua;//移动向最终的朝向

        Quaternion final_qua;//站稳后的朝向

        Quaternion cameraq;//摄像头的旋转角度
        public static SSMoveToAction boatmove( Vector3 position,Transform camera){
            SSMoveToAction action = ScriptableObject.CreateInstance<SSMoveToAction>();
            action.end_position = position;
            action.maincamera = camera;
            //摄像头翻转
            if(camera.rotation==Quaternion.Euler(0,0,0))action.cameraq = Quaternion.Euler(180,0,180);
            else action.cameraq = Quaternion.Euler(0,0,0);
            action.kind = 2;
            action.move_sign=1;
            action.rotaspeed = 200;
            action.mspeed = 2;
            return action;
        }
        // -90前 0右 90后 180左 
        public static SSMoveToAction movetoland(GameObject role,LandModel land){
            SSMoveToAction action = ScriptableObject.CreateInstance<SSMoveToAction>();
            Vector3 position = land.GetEmptyPosition();
            action.mid_position = new Vector3(position.x,role.transform.position.y,role.transform.position.z);
            action.end_position = new Vector3(position.x,role.transform.position.y,position.z);
            if(land.GetLandSign() == 1){//走下初始大陆上的转向方式
                action.mid_qua = Quaternion.Euler(0,90,0);
                if(position.z>role.transform.position.z)action.end_qua= Quaternion.Euler(0,0,0);
                else action.end_qua = Quaternion.Euler(0,180,0);
                action.final_qua  = Quaternion.Euler(0,-90,0);
            }
            else{//走下对面大陆上的转向方式
                action.mid_qua = Quaternion.Euler(0,-90,0);
                if(position.z>role.transform.position.z)action.end_qua= Quaternion.Euler(0,0,0);
                else action.end_qua = Quaternion.Euler(0,180,0);
                action.final_qua  = Quaternion.Euler(0,90,0);
            }
            action.kind = 1;
            action.move_sign = 1;
            return action;
        }

        public static SSMoveToAction movetoboat(GameObject role,BoatModel boat){
            SSMoveToAction action = ScriptableObject.CreateInstance<SSMoveToAction>();
            Vector3 position = boat.GetEmptyPosition();
            action.mid_position = new Vector3(role.transform.position.x,role.transform.position.y,position.z);
            action.end_position = new Vector3(position.x,role.transform.position.y,position.z);
            if(boat.GetBoatSign() == 1){//船在初始大陆上的转向方式
                if(position.z>role.transform.position.z)action.mid_qua = Quaternion.Euler(0,0,0);
                else action.mid_qua = Quaternion.Euler(0,180,0);
                action.end_qua = action.final_qua = Quaternion.Euler(0,-90,0);
            }
            else{//船在对面大陆上的转向方式
                if(position.z>role.transform.position.z)action.mid_qua = Quaternion.Euler(0,0,0);
                else action.mid_qua = Quaternion.Euler(0,180,0);
                action.end_qua = action.final_qua = Quaternion.Euler(0,90,0);
            }
            action.kind = 1;
            action.move_sign = 1;
            return action;
        }

        public int getmovesign(){
            return move_sign;
        }
        public override void Start(){

        }

        public override void Update()
        {
            if(kind == 1)roleUpdate();
            else if(kind == 2) boatUpdate();
            if(move_sign == 0)
            {
                this.destroy = true;
                // 完成动作后进行动作回掉
                this.Callback.SSActionEvent(this);
            }
        }
        void boatUpdate(){
            if(move_sign==1){
                //渐慢的镜头旋转
                maincamera.rotation = Quaternion.RotateTowards(maincamera.rotation, cameraq, rotaspeed*Time.deltaTime);
                if(rotaspeed>0)rotaspeed -= 120*Time.deltaTime>rotaspeed?rotaspeed: 120*Time.deltaTime;
                this.Transform.position = Vector3.MoveTowards(this.Transform.position, end_position,mspeed * Time.deltaTime);
                if(this.Transform.position==end_position)move_sign=0;
            }
        }
        void roleUpdate(){
            if(move_sign == 1){// 移动前转向
                this.Transform.rotation = Quaternion.RotateTowards(this.Transform.rotation, mid_qua, rotaspeed*Time.deltaTime);
                if(this.Transform.rotation==mid_qua)move_sign=2;
            }
            else if(move_sign == 2){//移动到中间
                this.Transform.position = Vector3.MoveTowards(this.Transform.position, mid_position, mspeed * Time.deltaTime);
                if (this.Transform.position == mid_position)move_sign=3;
            }
            else if(move_sign == 3){//在中间转向
                this.Transform.rotation = Quaternion.RotateTowards(this.Transform.rotation, end_qua, rotaspeed*Time.deltaTime);
                if(this.Transform.rotation==end_qua)move_sign=4;
            }
            else if(move_sign == 4){//移动到最终目的地
                this.Transform.position = Vector3.MoveTowards(this.Transform.position, end_position, mspeed * Time.deltaTime);
                if (this.Transform.position == end_position)move_sign=5;
            }
            else if(move_sign == 5){//在最终目的地转向
                this.Transform.rotation = Quaternion.RotateTowards(this.Transform.rotation, final_qua, rotaspeed*Time.deltaTime);
                if(this.Transform.rotation==final_qua)move_sign=0;
            }
        }

        public int moves(){
            return move_sign;
        }
    }

    public class SSSequenceAction : SSAction, ISSActionCallback{

        public List<SSAction> sequence; 
        public int repeat = -1;
        public int start = 0; 

        // 创建并返回动作序列的实例
        public static SSSequenceAction GetSSSequenceAction(int repeat, int start, List<SSAction> sequence){
            SSSequenceAction action = ScriptableObject.CreateInstance<SSSequenceAction>();
            action.repeat = repeat;
            action.sequence = sequence;
            action.start = start;
            return action;
        }
        
        // 在 Update 中执行当前动作
        public override void Update(){
            if (sequence.Count == 0) return;
            if (start < sequence.Count)
            {
                sequence[start].Update();
            }
        }

        // 更新当前执行的动作
        public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Complete, 
                                    int intParam = 0, string strParam = null, Object objectParam = null) {
            source.destroy = false;
            this.start++;
            if (this.start >= sequence.Count)
            {
                this.start = 0;
                if (repeat > 0) repeat--;
                if (repeat == 0)
                {
                    this.destroy = true;
                    this.Callback.SSActionEvent(this);
                }
            }
        }

        // Use this for initialization
        public override void Start(){
            foreach (SSAction action in sequence)
            {
                action.GameObject = this.GameObject;
                action.Transform = this.Transform;
                action.Callback = this;
                action.Start();
            }
        }

    

        // 执行完毕后销毁动作
        void OnDestroy()
        {
            foreach (SSAction action in sequence)
            {
                Destroy(action);
            }
        }

        
    }

    public class SSActionManager : MonoBehaviour{
        private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
        private List<SSAction> waitingAdd = new List<SSAction>();
        private List<int> waitingDelete = new List<int>();

        protected void Update(){
            foreach (SSAction action in waitingAdd){
                actions[action.GetInstanceID()] = action;
            }
            waitingAdd.Clear();

            foreach (KeyValuePair<int, SSAction> KeyValue in actions){
                SSAction action = KeyValue.Value;
                if (action.destroy){
                    waitingDelete.Add(action.GetInstanceID()); // release action
                }
                else if (action.enable){
                    action.Update(); // update action
                }
            }

            foreach (int key in waitingDelete){
                SSAction action = actions[key];
                actions.Remove(key);
                Destroy(action);
            }
            waitingDelete.Clear();
        }
        protected void Start(){ 

        }
        // 执行动作
        public void RunAction(GameObject gameObject,SSAction action, ISSActionCallback callback){
            action.GameObject = gameObject;
            action.Transform = gameObject.transform;
            action.Callback = callback;
            waitingAdd.Add(action);
            action.Start();
        }
        public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Complete,
            int intParam = 0, string strParam = null, Object objectParam = null){
            
        }

    }
    public class ActionManager : SSActionManager, ISSActionCallback  
    {

        private SSMoveToAction boat_move;     
        private SSMoveToAction char_move;     

        public ISceneController sceneController;

        protected new void Start()
        {
            sceneController = (ISceneController)SSDirector.GetInstance().CurrentScenceController;
            char_move =boat_move = ScriptableObject.CreateInstance<SSMoveToAction>();
        }
        public void moveBoat(GameObject boat,Vector3 dest, Transform maincamera)
        {
            boat_move = SSMoveToAction.boatmove(dest,maincamera);
            this.RunAction(boat, boat_move, this);
        }

        public void movetoland(GameObject role,LandModel land){
            char_move  = SSMoveToAction.movetoland(role,land);
            this.RunAction(role,char_move,this);
        }
        public void movetoboat(GameObject role,BoatModel boat){
            char_move  = SSMoveToAction.movetoboat(role,boat);
            this.RunAction(role,char_move,this);
        }
        public int getboatmovesign(){
            return boat_move.moves();
        }

        public int getrolemovesign(){
            return char_move.moves();
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值