1. 程式人生 > >unity3D MiniMap等比例對映的實現(二) 通過RawImage UV資訊控制小地圖的移動

unity3D MiniMap等比例對映的實現(二) 通過RawImage UV資訊控制小地圖的移動

上一篇為大家介紹了Image簡單的實現Player的移動並對映到小地圖上:上篇連結點選開啟連結

本篇為大家分享的是通過RawImage來實現實現小地圖的縮放:最終實現效果Player的移動會控制RawImage的UV資訊的改變使得RawImage移動,呈現一下最終效果:

具體UI的調整適配這裡我就不多介紹了,介面的佈局調整可以看上一篇 這裡只是將Image換成了RawImage去實現,用面板Plane來代替記得加Collider哦

一般情況下我們用RawImage去實現精靈動畫當然也是通過UV資訊的大小調整

UVRect:X  Y 表示比例的起點 ;W H表示比例的寬和高

WH用來調節小地圖的事業範圍:   比如這裡我除錯的WH設定為0.25,0.25就將RawImage縮小了0.25,在Canvas下始終顯示圖片的1/4.

XY用來控制小地圖的移動,也是與Player的位置實時更新的

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

public class TestMap : MonoBehaviour
{
    public Transform player;
    public Transform myTerrain;
    Collider myTerrainCol;
    RectTransform litMap;
    RectTransform sonRect;
    float widthRate;
    float heightRate;
    RawImage rawImage;
    Vector3 tmpAngle;
    float timeCount = 0;
    Rect rowRect;

    void Start()
    {
        myTerrain = GameObject.FindGameObjectWithTag("Terrian").transform;
        myTerrainCol = myTerrain.GetComponent<Collider>();
        litMap = transform.parent.GetComponent<RectTransform>();
        sonRect = transform.GetComponent<RectTransform>();
        rawImage = transform.parent.GetComponent<RawImage>();

    }

    void Update()
    {
        timeCount += Time.deltaTime;
        if (timeCount > 0.5f)
        {
            timeCount = 0;
            UpdatePos();
        }
    }
    void UpdatePos()
    {
        widthRate = (player.transform.position.x - myTerrain.position.x) / myTerrainCol.bounds.size.x;
        heightRate = (player.transform.position.z - myTerrain.position.z) / myTerrainCol.bounds.size.z;
        //這是相對於RawImage的偏移量 根據UV取得的WH比例比如WH為0.25,那麼加的位移偏移量為0.5-1/8=0.375 WH為0.5那麼加的位移偏移量為0.5-1/4=0.25
        rowRect = rawImage.uvRect;
        rowRect.x = widthRate + 0.375f;
        rowRect.y = heightRate + 0.375f;
        rawImage.uvRect = rowRect;

        tmpAngle = sonRect.localEulerAngles;
        tmpAngle.z = 90 - player.localEulerAngles.y;
        sonRect.localEulerAngles = tmpAngle;

    }
}

但是以上操作為發現一個問題就是當移動到邊界時會暴露,超出視野,當然真實專案中是絕對不允許這種的,你可以偷個懶一般RPG場景的的邊緣留出來這些可能暴露的範圍,讓玩家限定範圍不在場景邊緣移動就好啦~當然也不是沒有解決的辦法

這時我們就要加限制條件了,有兩種實現方法:

方案一:你可以在要暴露的範圍控制WH的範圍,越往邊界走,調節WH的可視範圍越大;

方案二:通過調節當要超出事業範圍時控制UV資訊的XY不再發生改變,而是通過調節Player的移動位置更新,實現方法就和Image更新位置的操作一樣了,

但是這個限定條件個人覺得很繁瑣,要加多層判定,這裡只提供大致思路  我做了幾個判定後發現可以限定視野不會暴露,但是PlayerIcon的位置會有微小的不同步,自己測試一下就好了

以下是我做了視野不會超出視野範圍的限定,實現效果就是我前面附上的動圖操作,也許你有更好的解決方案歡迎交流

吐舌頭

下一篇我將會向大家介紹第三種實現等比例對映小地圖的方案------通過ScrollView去實現

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

public class TestMap : MonoBehaviour
{
    public Transform player;
    public Transform myTerrain;
    Collider myTerrainCol;
    RectTransform litMap;
    RectTransform sonRect;
    float widthRate;
    float heightRate;
    RawImage rawImage;
    Vector3 tmpAngle;
    float timeCount = 0;
    Rect rowRect;
    Vector2 tmpPos = Vector2.zero;

    void Start()
    {
        myTerrain = GameObject.FindGameObjectWithTag("Terrian").transform;
        myTerrainCol = myTerrain.GetComponent<Collider>();
        litMap = transform.parent.GetComponent<RectTransform>();
        sonRect = transform.GetComponent<RectTransform>();
        rawImage = transform.parent.GetComponent<RawImage>();
        

    }

    void Update()
    {
        timeCount += Time.deltaTime;
        if (timeCount > 0.5f)
        {
            timeCount = 0;
            UpdatePos();
        }
    }
    void UpdatePos()
    {
        widthRate = (player.transform.position.x - myTerrain.position.x) / myTerrainCol.bounds.size.x;
        heightRate =(player.transform.position.z - myTerrain.position.z) / myTerrainCol.bounds.size.z;
       // rowRect = rawImage.uvRect;
       // rowRect.x = widthRate +0.375f;
       // rowRect.y = heightRate +0.375f;
       // rawImage.uvRect = rowRect;


        rowRect = rawImage.uvRect;

        if (widthRate + 0.375f > 0f && widthRate + 0.375f < 0.75f && heightRate + 0.375f > 0 && heightRate + 0.375f < 0.75f)
        {
            rowRect.x = widthRate + 0.375f;
            rowRect.y = heightRate + 0.375f;
        }
        else
        {           
            if (widthRate + 0.375f <= 0f)
            {
                rowRect.x = 0;
            }
            else if (widthRate + 0.375f >= 0.75)
            {
                rowRect.x = 0.75f;
            }
            else if (heightRate + 0.375f >= 0.75)
            {
                rowRect.y = 0.75f;
            }
            else if (heightRate + 0.375f <= 0f)
            {
                rowRect.y = 0;
            }
            //tmpPos.x = litMap.sizeDelta.x * widthRate;
            //tmpPos.y = litMap.sizeDelta.y * heightRate;
            //sonRect.anchoredPosition = tmpPos;
        }

        
        rawImage.uvRect = rowRect;
        Debug.Log("rowRect==="+rowRect);
        Debug.Log("rawImage.uvRect===" + rawImage.uvRect);
        tmpAngle = sonRect.localEulerAngles;
        tmpAngle.z = 90 - player.localEulerAngles.y;
        sonRect.localEulerAngles = tmpAngle;

    }

   
}