unity 制作小地图

需求:制作一个正方形的小地图,如果小地图素材不是正方形,则美术同学填补成正方形
(据策划大佬说,王者荣耀的小地图就是这样的)

//小地图逻辑
public class MiniMap
	{
		//小地图素材
		private string mPic;
		public string Pic => mPic;
		//场景左下角坐标起始点(小地图可能不是从场景的00点开始)
		private Vector3 mSceneLeftDown;
		public Vector3 SceneLeftDown => mSceneLeftDown;
		
		//场景右上角坐标终点(小地图的终点可能不是场景终点)
		private Vector3 mSceneRightTop;
		public Vector3 SceneRightTop => mSceneRightTop;

		//小地图素材左下角坐标点(小地图可能是美术补色)
		private Vector3 mPngLeftDown;
		public Vector3 PngLeftDown => mPngLeftDown;
		
		//小地图素材右上角坐标点(小地图可能是美术补色)
		private Vector3 mPngRightTop;
		public Vector3 PngRightTop => mPngRightTop;
		
		//小地图的展示角度有可能和场景角度不一致,这里的方案是计算完坐标点后
		//旋转UI控件
		private float mUIRotation;
		public float UIRotation => mUIRotation;
		
		//旋转后的UI控件,会有偏移值
		private Vector3 mUIOffset;
		public Vector3 UIOffset => mUIOffset;
		//png和UI的缩放比,例如UI控件300,小地图素材是512,那么缩放比是0.59
		private float mPngToUI = 0.59f;
		//场景和png的缩放比,例如场景是100*100,小地图素材是512*512
		//那么缩放比就是5.12
		private Vector3 mSceneToPngScale;
		Vector3 mPngToUIScale;

		public MiniMap(int sn)
		{
			Vector3 deltaScene = mSceneRightTop - mSceneLeftDown;
			Vector3 deltaPng = PngRightTop - PngLeftDown;

			mPngToUIScale = Vector3.one * mPngToUI;
			mSceneToPngScale = new Vector3(deltaPng.x / deltaScene.x, deltaPng.y / deltaScene.y, 1);
		}

		public Vector3 ScenePositionToUIPosition(Vector3 scenePosition)
		{
			Vector3 pngPos = ScenePositionToPngPosition(scenePosition);
			return PngToUIPosition(pngPos);
		}

		private Vector3 PngToUIPosition(Vector3 pngPosition)
		{
			return new Vector3(pngPosition.x * mPngToUIScale.x, pngPosition.y * mPngToUIScale.y, 1);
		}

		private Vector3 ScenePositionToPngPosition(Vector3 scenePosition)
		{
			scenePosition = ScenePositionTo2DPosition(scenePosition);
			Vector3 deltaScene = scenePosition - mSceneLeftDown;
			return PngLeftDown + new Vector3(deltaScene.x * mSceneToPngScale.x, deltaScene.y * mSceneToPngScale.y, 1);
		}

		private Vector3 ScenePositionTo2DPosition(Vector3 scenePosition)
		{
			return new Vector3(scenePosition.x, scenePosition.z, 0);
		}

	}
//UI逻辑
    public class MiniMapView : Monobehaviour
    {
    //地图可放大,可缩小
		private enum EType
		{
			Small,
			Big,
		}
	//地图上显示自己,其他玩家和Npc
		private enum EMapKey
		{
			Self,
			Other,
			Npc,
		}
		//当前是大地图还是小地图
		private EType mCurType = EType.Small;
		//小地图图片的控件
        private RawImage mImg;
        //放大,缩小按钮
        private GameObject mBtnBig, mBtnSmall;
        //小地图逻辑
		private MiniMap mMap;
		//小地图父节点,用来播放放大缩小动画
		private GameObject mImgGo;
		private TweenScale mTween;
		//玩家自己
		private MapKey mSelf;
		//其他玩家
		private List<MapKey> mListOther = new List<MapKey>();
		//需要在小地图显示标识的NPC
		private List<MapKey> mListNpc = new List<MapKey>();
		//自己,其他玩家,NPC标识的控件模板
		private GameObject mSelfTemplate, mOtherTemplate, mNpcTemplate;
		
		//点击小地图上的标识,显示玩家名字的tips
		private GameObject mTipPanel;
		private GameObject mTipName;

		void OnInit()
		{
			//给控件赋值,注册点击事件
		}

		public void OnShow(object param = null)
		{
			mMap = new MiniMap((int)param);
			mSelf = new MapKey(mSelfTemplate, mMap, EMapKey.Self);
			mSelf.SetData(Role);
			//给小地图的图片赋值,这里就不写了
			SetImgRotAndPos();
			mCurType = EType.Small;
			RefreshBtn();
			MakeOtherKey();
			MakeNpc();
		}
		//设置图片的角度和便宜位置
		private void SetImgRotAndPos()
		{
			if (mMap == null) return;
			mImgGo.transform.rectTransform().anchoredPosition3D = mMap.UIOffset;
			mImgGo.transform.localEulerAngles = new Vector3(0, 0, mMap.UIRotation);
		}

	

		//刷新标识位置
		protected override void Update()
		{
			base.Update();
			if (mMap == null) return;
			UpdateSelfPos();
			UpdateNpcPos();
			UpdateOtherPos();
		}

		private void UpdateSelfPos()
		{
			mSelf?.UpdatePos();
		}

		private void UpdateOtherPos()
		{
			for(int i = 0;i < mListOther.Count;++i)
			{
				mListOther[i].UpdatePos();
			}
		}

		private void UpdateNpcPos()
		{
			for (int i = 0; i < mListNpc.Count; ++i)
			{
				mListNpc[i].UpdatePos();
			}
		}
		//当别的角色上下线,刷新其他玩家NPC标识
		private void RefreshOther()
		{
			for(int i = 0;i < mListOther.Count;++i)
			{
				mListOther[i].RefreshOther();
			}
		}
		//创建其他角色标识
		private void MakeOtherKey()
		{
			List<Role> list;
			if (list == null || list.Count <= 0)
			{
				ResetOther();
				return;
			}
			int i = 0;
			for(;i < list.Count;++i)
			{
				if (i >= mListOther.Count)
				{
					GameObject go = GameObject.Instantiate(mOtherTemplate);
					go.transform.SetParent(mOtherTemplate.transform.parent, false);
					MapKey mapKey = new MapKey(go,mMap, EMapKey.Other);
					mListOther.Add(mapKey);
				}
				mListOther[i].SetData(list[i]);
				mListOther[i].SetVisible(true);
			}
			for(;i < mListOther.Count;++i)
			{
				mListOther[i].SetVisible(false);
			}
		}

		private void ResetOther()
		{
			for(int i = 0;i < mListOther.Count;++i)
			{
				mListOther[i].SetVisible(false);
			}
		}
	//创建NPC标识
		private void MakeNpc()
		{
			if(mMap == null)
			{
				ResetNpc();
				return;
			}
			List<NpcInfo> list = ModelManager.Get<NpcModel>().GetListMapNpcByScene(mMap.Sn);
			if(list == null || list.Count <= 0)
			{
				ResetNpc();
				return;
			}
			int i = 0;
			for(;i < list.Count;++i)
			{
				if(i >= mListNpc.Count)
				{
					GameObject go = GameObject.Instantiate(mNpcTemplate);
					go.transform.SetParent(mNpcTemplate.transform.parent, false);
					MapKey mapKey = new MapKey(go,mMap, EMapKey.Npc);
					mListNpc.Add(mapKey);
				}
				mListNpc[i].SetData(list[i]);
				mListNpc[i].SetVisible(true);
			}
			for(;i < mListNpc.Count;++i)
			{
				mListNpc[i].SetVisible(false);
			}
		}

		private void ResetNpc()
		{
			for(int i = 0;i < mListNpc.Count;++i)
			{
				mListNpc[i].SetVisible(false);
			}
		}
		//刷新放大,缩小按钮
		private void RefreshBtn()
		{
			SetVisible(mBtnBig, mCurType == EType.Small && !mIsPlaying);
			SetVisible(mBtnSmall, mCurType == EType.Big && !mIsPlaying);
		}


		//点击放大按钮
		private void OnClickBig(GameObject obj)
		{
			mCurType = EType.Big;
			PlayTween();
			RefreshBtn();
		}
		//点击缩小按钮
		private void OnClickSmall(GameObject obj)
		{
			mCurType = EType.Small;
			PlayTween(true);
			RefreshBtn();
		}
		//播放放大缩小动画,动画期间不能隐藏按钮,防止误点击
		private bool mIsPlaying = false;
		private void PlayTween(bool isReverse = false)
		{
			mIsPlaying = true;
			if (mTween == null) return;
			if(!isReverse)
			{
				mTween.Play();
			}
			else
			{
				mTween.PlayReverse();
			}
			TimerManager.Instance.AddTimer(0.15f, () =>
			 {
				 mIsPlaying = false;
				 RefreshBtn();
			 });
		}
	//点击标识,显示名字,三秒后隐藏
		private void OnClickKey(CharacterBase info)
		{
			if (info == null) return;
			string str = info.Name;
			if(info is Role)
			{
				Role role = (Role)info;
				if (role != null && !role.IsOnline)
				{
					str = str + "(离线)";
				}
			}

			SetText(mTipName, str);
			SetVisible(mTipPanel, true);
			TimerManager.Instance.AddTimer(3f, () =>
			{
				SetVisible(mTipPanel, false);
			});
		}


//小地图上的标识
		private class MapKey : WindowView
		{
			private EMapKey mKeyType = EMapKey.Self;
			//其他玩家上下线的节点
			private GameObject mOnline, mOffline;
			//NPC的图标
			private Image mNpcImg;
			//角色信息
			private CharacterBase mInfo;
			private MiniMap mMap;

			public MapKey(GameObject parent, MiniMap map, EMapKey keyType = EMapKey.Self)
			{
				mParent = parent;
				mKeyType = keyType;
				mMap = map;

				if(mKeyType == EMapKey.Other)
				{
					mOnline;
					mOffline;
				}
				else if (mKeyType == EMapKey.Npc)
				{
					mNpcImg ;
				}
			}
			//设置NPC图标
			public void SetData(Npc info)
			{
				if (info == null) return;
				mInfo = info;
				SetVisible(info.Visible);
			}
			//设置角色标识
			public void SetData(Role info)
			{
				if (info == null) return;
				mInfo = info;
				if (mKeyType == EMapKey.Other)
				{
					RefreshOther(info);
				}
			}
			//其他玩家上下线
			public void RefreshOther(Role info = null)
			{
				if (info == null)
				{
					info = (Role)mInfo;
				}
				if (info == null) return;
				SetVisible(mOnline, info.IsOnline);
				SetVisible(mOffline, !info.IsOnline);
			}
		//设置标识位置
			public void UpdatePos()
			{
				if (mMap == null || mInfo == null) return;
				SetVisible(mInfo.Visible);
				Parent.transform.localPosition = mMap.ScenePositionToUIPosition(mInfo.GetCurPos());
			}

			private void OnClickKey(GameObject obj)
			{
				//点击标识,显示名字tips
			}
		}

	}
}
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity3D是一款强大的游戏开发引擎,可以用于制作各种类型的游戏,包括小地图。小地图可以帮助玩家在游戏中快速定位自己的位置,了解周围的环境和目标位置。下面是制作Unity3D小地图的步骤: 1.首先,需要创建一个小地图的背景图。可以使用2D图片或者3D模型作为地图的背景。根据游戏的需求选择合适的背景。 2.接下来,创建一个摄像机对象,并将其设置为渲染到一个RenderTexture上。RenderTexture是一个可以用于将某个摄像机渲染的图像输出到纹理的类。在这个RenderTexture上设置小地图的尺寸和位置。 3.将创建的摄像机对象添加到主摄像机上。这样可以实现将主摄像机的渲染图像投影到小地图的背景图上。 4.创建小地图上的角色或者目标的图标。可以使用2D图片或者3D模型作为图标,根据游戏需求选择合适的样式。 5.根据角色或者目标的位置,将图标放置在小地图的对应位置上。可以通过坐标转换等方式将世界坐标转换为小地图上的坐标。 6.在游戏进行中,更新小地图上的角色或者目标的位置。可以通过实时获取角色或者目标的位置信息,然后将图标移动到对应的位置。 7.可以在小地图上添加一些标记物,比如重要地点、敌人位置等。这样可以帮助玩家更好地了解游戏世界的结构和情况。 通过以上步骤,就可以制作出一个基本的Unity3D小地图。当然,在实际制作中还可以根据游戏的需求进行一些定制和优化,比如添加一些特效、增加互动功能等,以提升游戏体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值