• 【Unity之竖屏游戏制作】如何做一个竖屏的手机游戏


    在这里插入图片描述


    👨‍💻个人主页@元宇宙-秩沅

    👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

    👨‍💻 本文由 秩沅 原创

    👨‍💻 收录于专栏Unity基础实战

    🅰️




    效果演示

    在这里插入图片描述


    🎶(1 添加分辨率


    在这里插入图片描述

    在这里插入图片描述


    🎶(2生成地图


    普通矩形地图生成


    在这里插入图片描述

    菱形矩形地图生成

    • 单排生成

    在这里插入图片描述

    • 双排铺满

    在这里插入图片描述

    • 添加缓存池的本质其实就是资源的循环利用,减少多次CG。也就是说,当我们需要销毁一个物体的时候我们需要用到的story,但是多次的destroy,它会触发我们的CG回收,那此时我们如果说用一个列表或者是字典。形成了一个缓存池,让他临时存放,我们需要多次销毁的一个物体的话,那么它就避免了多次产生C机的回收机制。此时我们可以选择让存进去的物体失活,需要的时候再激活,把它存取出来,让就可以进行一个循环的利用。

    🎶(3 未添加缓存池之前


    在这里插入图片描述


    🎶(4 添加缓存池后


    在这里插入图片描述


    🎶(5缓存池 脚本


    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Events;
    
    /// 
    /// 抽屉数据 
    /// 
    public class PoolData
    {
        //抽屉中 对象挂载的父节点
        public GameObject fatherObj;
        //对象的容器
        public List<GameObject> poolList;
    
        public PoolData(GameObject obj, GameObject poolObj)
        {
            //给我们的抽屉 创建一个父对象 并且把他作为我们pool(衣柜)对象的子物体
            fatherObj = new GameObject(obj.name);
            fatherObj.transform.parent = poolObj.transform;
            poolList = new List<GameObject>() {};
            PushObj(obj);
        }
    
        /// 
        /// 往抽屉里面 压都东西
        /// 
        /// 
        public void PushObj(GameObject obj)
        {
            //失活 让其隐藏
            //obj.SetActive(false);  //可放在外部去激活
            //存起来
            poolList.Add(obj);
            //设置父对象
            obj.transform.parent = fatherObj.transform;
        }
    
        /// 
        /// 从抽屉里面 取东西
        /// 
        /// 
        public GameObject GetObj(Transform parent)  //参数为需要设置的父对象
        {
            GameObject obj = null;
            //取出第一个
            obj = poolList[0];
            //对物体的Y轴进行约束
            obj.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezePositionY;
            poolList.RemoveAt(0);
            //激活 让其显示
            obj.SetActive(true);
            //断开了父子关系
            obj.transform.SetParent(parent);
    
            return obj;
        }
    }
    
    /// 
    /// 缓存池模块 
    /// 
    public class PoolManager : SingleManager <PoolManager>
    {
        //缓存池容器 (衣柜)
        public Dictionary<string, PoolData> poolDic = new Dictionary<string, PoolData>();
    
        private GameObject poolObj;
    
        /// 
        /// 从缓存池中拿东西
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public void GetObj(string name, Transform parent, UnityAction<GameObject> callBack) //第三个参数为挂载的父对象
        {
           
            if(poolDic.ContainsKey(name) && poolDic[name].poolList.Count > 0)
            {
               
        
                callBack(poolDic[name ].GetObj(parent));
            }
            else
            {
                //同步加载
                GameObject obj = GameObject.Instantiate(ResManager.GetInstance().Load<GameObject>("prefabs/" + name));
                obj.name = name;  
                callBack(obj);  //返回实例化的物品给委托
            
                通过异步加载资源 创建对象给外部用
                //ResManager .GetInstance().LoadAsync("prefabs/"+name, (o) =>
                //{
                //    o.name = name;
                //    callBack(o);
                //});
    
                //obj = GameObject.Instantiate(Resources.Load(name));
                //把对象名字改的和池子名字一样
                //obj.name = name;
            }
        }
    
        /// 
        /// 换暂时不用的东西给池子
        /// 
        public void PushObj(string name, GameObject obj)
        {
            if (poolObj == null)
                poolObj = new GameObject("Pool");
    
            //里面有抽屉
            if (poolDic.ContainsKey(name))
            {
                poolDic[name].PushObj(obj);
            }
            //里面没有抽屉
            else
            {          
                poolDic.Add(name, new PoolData(obj, poolObj));
            }
        }
    
    
        /// 
        /// 清空缓存池的方法 
        /// 主要用在 场景切换时
        /// 
        public void Clear()
        {
            poolDic.Clear();
            poolObj = null;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138

    🎶(6简单的prime算法——十字检测


    在这里插入图片描述

    在这里插入图片描述

    • 1.首先全部判定为墙,最外的为路包裹墙(类似于防止数组越界
      在这里插入图片描述
    • 2.红色为它的检测范围(假设检测点在如图所示的位置)———(可先忽略此步骤)

    ——————在这里插入图片描述

    • 3.该检测点(紫色)需要在起点的旁边或者外墙旁边,已保证它可以生成主路线而不是死迷宫
      在这里插入图片描述
      在这里插入图片描述
    • 4.生成后是这样的,没有出口,它不会自动打破墙
      在这里插入图片描述
    • 5,所以需要我们自己检测一波打出一个出口

    在这里插入图片描述

    • 运行结果
      在这里插入图片描述

    c#版本的十字Prim


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace algorithm
    {
        /// 
        /// 该Prom算法,初始化时全部是墙
        /// 
        class PrimOfAlgorithm
        {
    
            public const int max = 40;
            int[,] Maze = new int[max  , max ];  //默认全为0 ,全为墙
            Random random = new Random();
            //X和Y方向的队列
            List<int> X = new List<int>();
            List<int> Y = new List<int>();
    
            /// 
            /// 生成迷宫
            /// 
            public  void CreatMap()
            {
                //设置迷宫进口
                Maze[2, 1] = 1;
             
            
                //将最外围设置为路,包裹最外层的的墙,防止出界
                for (int i = 0; i < max; i++)
                {
                    Maze[i ,0]= 1;
                    Maze[i, max - 1] = 1;
                    Maze[0, i] = 1;
                    Maze[max - 1, i] = 1;  
                }
    
                //设置一个坐标.该检测点需要在起点的旁边,或者旁边是外围路
    
                X.Add (2);
                Y.Add (2);
    
                while( Y.Count > 0)
                {
                   
                    int index = random.Next(0, X.Count - 1); //随机性则有错综复杂的效果
                
                    int xPosition=  X[index];
                    int yPosition = Y[index];
    
                    //判断上下左右是否有路
                    int count = 0;
                   
                    for (int i = xPosition - 1; i <= xPosition + 1; i++) //左右位置
                    {
                        for (int j = yPosition - 1; j <= yPosition + 1; j++) //上下位置
                        {
                            //判断它是不是十字检测中的点,和判断它是否为路
                            if (Math.Abs(xPosition - i) + Math.Abs(yPosition - j) == 1 && Maze[i,j] > 0) 
                             {
                                ++count; //路++  
                             }
                        }
                    }
    
                    //如果十字检测的路标记少于或等于1条?(为甚不直接小于1呢,因为它要保证生成一条主路)
                    if (count <= 1)
                    {
                        //将此刻的位置变成路
                        Maze[xPosition, yPosition] = 1;
    
                        for (int i = xPosition - 1; i <= xPosition + 1; i++)
                        {
                            for (int j = yPosition - 1; j <= yPosition + 1; j++)
                            {
                                //判断它是不是十字检测中的点并且是墙
                                if (Math.Abs(xPosition - i) + Math.Abs(yPosition - j) == 1 && Maze[i, j] == 0)
                                {
                                    //把十字检测到的墙放入XY墙列表
                                    X.Add(i);
                                    Y.Add(j);
                                }
                            }
    
                        }
                    }
               
                    //删除列表中已经变成路的点
                    X.RemoveAt(0 + index );
                    Y.RemoveAt(0 + index ); //记住不能是Remove
                                  
                }
    
                //设置迷宫出口(出口不可能是四个底脚)
                for (int i = max - 3; i >= 0; i--)
                {
                    if (Maze[i, max - 3] == 1)
                    {
                        Maze[i, max - 2] = 1;
                        break;
                    }
                }
                //画迷宫
                for (int i = 0; i < max; i++)
                {
                    for (int j = 0; j < max; j++)
                    {
                        if (Maze[i, j] == 1)
                            Console.Write("  ");
                        else
                            Console.Write("囚");
                    }
                    Console.WriteLine();
                }
    
            }
    
    
            static void Main(string[] args)
            {
                PrimOfAlgorithm aa = new PrimOfAlgorithm();
             
                 aa.CreatMap();
               
            }
        }
    
    
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133

    c++版本的十字Prim


    
    #include 
    #include
    #include 
    using namespace std;
    static const int L = 44;
    void CreateMaze();
    int main()
    {
    	CreateMaze();
    }
     void CreateMaze() {
    	int Maze[L][L] = { 0 };
     
    
    	vector<int> X;
    	vector<int> Y;
    
    	//最外围设置为路,可以有效的保护里面一层墙体,并防止挖出界
    	for (int i = 0; i < L; i++) {
    		Maze[i][0] = 1;
    		Maze[0][i] = 1;
    		Maze[L - 1][i] = 1;
    		Maze[i][L - 1] = 1;
    	}
    
    	//设置迷宫进口
    	Maze[2][1] = 1;
    	
    	//任取初始值
    	X.push_back(2);
    	Y.push_back(2);
     
    	//当墙队列为空时结束循环
    	while (X.size()) {
    		//在墙队列中随机取一点
    		int r = rand() % X.size();
    		int x = X[r];
    		int y = Y[r];
     
    		//判读上下左右四个方向是否为路
    		int count = 0;
    		for (int i = x - 1; i < x + 2; i++) {	
    			for (int j = y - 1; j < y + 2; j++) {
    				if (abs(x - i) + abs(y - j) == 1 && Maze[i][j] > 0) {
    					++count;
    				}
    			}
    		}
     
    		if (count <= 1) {
    
    			Maze[x][y] = 1;
    
    			
    			//在墙队列中插入新的墙
    			for (int i = x - 1; i < x + 2; i++) {
    				for (int j = y - 1; j < y + 2; j++) {
    					
    					if (abs(x - i) + abs(y - j) == 1 && Maze[i][j] == 0) {
    						X.push_back(i);
    						Y.push_back(j);
    					}
    				}
    			}
    		}
     
    		//删除当前墙
    		X.erase(X.begin() + r);
    		Y.erase(Y.begin() + r);
    	}
     
    	//设置出口 (从最下往上面判断)
    	for (int i = L - 3; i >= 0; i--) {
    		if (Maze[i][L - 3] == 1) {
    			Maze[i][L - 2] = 1;
    			break;
    		}
    	}
     
    	//画迷宫
    	for (int i = 0; i < L; i++){
    		for (int j = 0; j < L; j++) {
    			if (Maze[i][j] == 1) printf("  ");
    			else printf("囚");
    		}
    		printf("\n");
    	}
    
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    Unity版本的十字Prim


    在这里插入图片描述

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    //-------------------------------------
    //—————————————————————————————————————
    //___________项目:      
    //___________功能:  生成迷宫
    //___________创建者:_____秩沅_____
    //_____________________________________
    //-------------------------------------
    public class Muze : MonoBehaviour
    {
        const int max = 40;
        //建立迷宫数组
        private int[,] mauz = new int [max ,max ];
    
        //墙列表
        private List<int > X = new List<int>();
        private List<int>  Y = new List<int>();
    
        //待加载资源
        private GameObject m_prefab_tile;
        private GameObject m_prefab_wall;
    
        private void Awake()
        {
            //资源加载
            m_prefab_tile = Resources.Load<GameObject>("prefabs/tile_white");
            m_prefab_wall = Resources.Load<GameObject>("prefabs/cube_bread");
        }
    
        void Start()
        {
            //初始坐标
            CreatMazu(new Vector2(2,1));
        }
    
        /// 
        /// 生成迷宫
        /// 
        public void CreatMazu( Vector2  position)
        {
            
              //step1.设置外墙
              for (int i = 0; i < max ; i++)
              {
                mauz[0, i] = 1;
                mauz[i, 0] = 1;
                mauz[i, max - 1] = 1;
                mauz[max - 1, i] = 1;
              }
    
              //step2.将初始位置放入队列当中
              X.Add((int )position.x);
              Y.Add((int )position.y);
            
            mauz[(int )position.x, (int )position.y] = 1; //它为起点
        
            while(X.Count > 0) //当列表里面有值的时候,也代表有墙的时候
            {
                //step3:从列表中取判定点
                int index = Random.Range(0, X.Count - 1); //从墙队列里面随机取一个下标
                int xPosition = X[index];
                int yPosition = Y[index];
    
                int count = 0;  //路的数量
    
                //step4:道路判定
                for (int i = xPosition - 1; i <= xPosition + 1; i++)
                {
                    for (int j = yPosition - 1; j <= yPosition + 1; j++)
                    {
                        if (Mathf.Abs(xPosition - i) + Mathf.Abs(yPosition - j) == 1 && mauz[i, j] > 0)
                        {
                            count++;
                        }
                    }
                }
    
                //step5:变成路,添加墙
                if (count <= 1)
                {
                    mauz[xPosition, yPosition] = 1; //变成路
    
                    for (int i = xPosition - 1; i <= xPosition + 1; i++)
                    {
                        for (int j = yPosition - 1; j <= yPosition + 1; j++)
                        {
                            if (Mathf.Abs(xPosition - i) + Mathf.Abs(yPosition - j) == 1 && mauz[i, j] == 0)
                            {
                                X.Add(i);
                                Y.Add(j);
                            }
                        }
                    }
                }
    
                //step6:移除列表里面的墙
                X.RemoveAt(0 + index);
                Y.RemoveAt(0 + index);
    
            }
    
      
               //step7:检测一下设置出口
              for (int i = max - 3 ; i  > 0 ; i-- )
              {
                  if(mauz[i,max - 3 ] == 1 )
                  {
                    mauz[i, max - 2] = 1;
                    break;
                  }
              }
    
             //step8:加载迷宫
              for (int i = 0; i < max ; i++)
              {
                  for (int j = 0; j < max ; j++)
                   {
                      if(mauz[i,j] == 0 )
                      {
                        GameObject ob =  Instantiate(m_prefab_wall,new Vector3(i * 0.254f, 0 , j * 0.254f),Quaternion.identity );
                        ob.transform.SetParent(transform);
                      }                
                    }
              }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129

    🎶(7prime算法生成的效果


    迷宫相对比较自然,但迷宫的分岔路会比较多,适合生成错综复杂的地图效果,主路不是特别明显

    • 初始化大地图,0代表墙,1代表道路,墙为地图边缘包裹

    • 靠近地图边缘随机选取状态为1的道路点,作为出生点a

    • 然后将 a 点周围所有的墙体点标记为待检测点,加入到待检测集合

    • 从待检测集合随机取一个点 b ,判断顺着它方向的下一个点 c,是否是道路

    • 如果是,则将这个待检测点墙体打通,将其移出待检测集合;将下一个点 c作为新的起点,重新执行第3步

    • 如果不是就把这个待检测点移出待检测集合,重新作为墙体点
      不断重复,直到待检测集合全部检查过,重新为空
      在这里插入图片描述
      🅰️


    🅰️


    【Unityc#专题篇】之c#进阶篇】

    【Unityc#专题篇】之c#核心篇】

    【Unityc#专题篇】之c#基础篇】

    【Unity-c#专题篇】之c#入门篇】

    【Unityc#专题篇】—进阶章题单实践练习

    【Unityc#专题篇】—基础章题单实践练习

    【Unityc#专题篇】—核心章题单实践练习


    你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!


    在这里插入图片描述


  • 相关阅读:
    什么是RPA?详解RPA工具和应用程序的工作原理!
    clickhouse的Distributed分布式表查询的性能陷阱
    顶级网络安全预测:近三分之一的国家将在三年内规范勒索软件响应
    锐捷网络C++开发实习有感
    S5PV210裸机(五):定时器
    荣耀MagicBook X 14 Pro锐龙版 2023 集显(FRI-H76)笔记本电脑原装出厂Windows11系统工厂模式安装包下载,带F10智能还原
    作为外贸业务员,为什么我经常随机轻松 就“捡“到精准潜在客户
    minio单点及分布式部署
    【leetcode】【2022/9/13】670. 最大交换
    magedu-第一、二周作业
  • 原文地址:https://blog.csdn.net/m0_64128218/article/details/134348065