Use QFramework para refactorizar el juego Zuma

material

Unidad - Juego Zuma
GitHub

ilustrar

Es suficiente usar QF para una escena y cambiar el prefabricado bajo UIRoot para lograr el cambio de panel.
Pero, por supuesto, debe haber un script de prueba que salte directamente al panel de prueba en la prueba, y la escena de prueba está reservada (de lo contrario, los principiantes no saben cómo restaurar la escena de prueba), por lo que el texto completo se divide por escena.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

----------------------------------------------------

01 La escena comienza a entrar (guión de panel, principalmente separación dinámica (función) estática (referencia de interfaz de usuario))

01 Primero cree un UIRoot (algunos en QF)

inserte la descripción de la imagen aquí

02 Haga que la interfaz de usuario sea correcta y agregue el script Bind a la interfaz de usuario a la que se debe hacer referencia (vea la imagen para ver la configuración predeterminada)

inserte la descripción de la imagen aquí

03 Arrástrelo para crear un prefabricado y CreateUICode generará dos scripts (la ubicación de generación automática es Scripts/UI en el directorio superior), uno para la referencia de UI (xxx. Designer), uno para la función (xxx) y el de la función se agregará automáticamente al prefabricado

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

xxxPanelData, xxxPanel (no llamado Panel, llamado xxxWindow, xxxUI lo que sea)

using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UnityEngine.SceneManagement;

namespace QFramework.Example
{
    
    
	public class StartGamePanelData : UIPanelData
	{
    
    
	}
	public partial class StartGamePanel : UIPanel
	{
    
    
		protected override void OnInit(IUIData uiData = null)
		{
    
    
			mData = uiData as StartGamePanelData ?? new StartGamePanelData();
			// please add init code here

			Screen.SetResolution(640, 1136, false);//宽,高,不可修改
			BtnStart.onClick.AddListener(() => {
    
    


				Debug.Log("StartGamePanel");
                SceneManager.LoadScene("01 SelectLevel");
            });
		}
		
		protected override void OnOpen(IUIData uiData = null)
		{
    
    
		}
		
		protected override void OnShow()
		{
    
    
		}
		
		protected override void OnHide()
		{
    
    
		}
		
		protected override void OnClose()
		{
    
    
		}
	}
}

xxxPanel.Diseñador

using System;
using UnityEngine;
using UnityEngine.UI;
using QFramework;

namespace QFramework.Example
{
    
    
	// Generate Id:29cfe4a1-ad1e-4350-a490-3bdf8cf34278
	public partial class StartGamePanel
	{
    
    
		public const string Name = "StartGamePanel";
		
		[SerializeField]
		public UnityEngine.UI.Button BtnStart;
		
		private StartGamePanelData mPrivateData = null;
		
		protected override void ClearUIComponents()
		{
    
    
			BtnStart = null;
			
			mData = null;
		}
		
		public StartGamePanelData Data
		{
    
    
			get
			{
    
    
				return mData;
			}
		}
		
		StartGamePanelData mData
		{
    
    
			get
			{
    
    
				return mPrivateData ?? (mPrivateData = new StartGamePanelData());
			}
			set
			{
    
    
				mUIData = value;
				mPrivateData = value;
			}
		}
	}
}

04 llamada, RrsKit.Init(); debe llamarse

/****************************************************
    文件:GameStart.cs
	作者:lenovo
    邮箱: 
    日期:2023/7/2 22:59:41
	功能:
*****************************************************/

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;


namespace QFramework.Example
{
    
    
    public class GameStart : MonoBehaviour
    {
    
    

        #region 生命

        /// <summary>首次载入</summary>
        void Awake()
        {
    
    
            ResKit.Init();
            UIKit.OpenPanel<StartGamePanel>();
            GameObject.DontDestroyOnLoad(gameObject);
        }
        

        #endregion 


    }

}




06 Escriba el nombre del paquete, márquelo (ResKit solo lo tiene en la lista de paquetes) y cree un paquete AB (QF tiene un ejemplo relacionado que no se puede ejecutar sin empaquetar; se edita, pero en realidad no es tan rápido)

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

06 efecto

inserte la descripción de la imagen aquí

-------------------------------------------------------------------------

02 Selección de escena

elección mundial

selección de nivel

Estrellas Nombre de la carpeta de complementos

En Unity, en la carpeta Complementos, se convertirá en un ensamblado de primer paso

--------------------------------------------------------

03 interfaz de juego de escena

modificar enumeración dividida

Buen punto para principiantes. Pero en realidad, los scripts integrados de Unity tienen enumeraciones escritas dentro de la clase.
inserte la descripción de la imagen aquí

GameUI se divide en el panel Pasar y el panel Fallar

Pase el panel

using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UnityEngine.SceneManagement;

namespace QFramework.Example
{
    
    
	public class SuccPanelData : UIPanelData
	{
    
    
	}
	public partial class SuccPanel : UIPanel
	{
    
    
		protected override void OnInit(IUIData uiData = null)
		{
    
    
			mData = uiData as SuccPanelData ?? new SuccPanelData();
			// please add init code here


			BtnNext.onClick.AddListener(() => {
    
     
                GameData.LevelIndex++;
                SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);			
			});
        }
		
		protected override void OnOpen(IUIData uiData = null)
		{
    
    
		}
		
		protected override void OnShow()
		{
    
    
		}
		
		protected override void OnHide()
		{
    
    
		}
		
		protected override void OnClose()
		{
    
    
		}
	}
}

panel de error

using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UnityEngine.SceneManagement;

namespace QFramework.Example
{
    
    
	public class GameOverPanelData : UIPanelData
	{
    
    
	}
	public partial class GameOverPanel : UIPanel
	{
    
    
		protected override void OnInit(IUIData uiData = null)
		{
    
    
			mData = uiData as GameOverPanelData ?? new GameOverPanelData();
			// please add init code here

			BtnReset.onClick.AddListener(()=>{
    
    
                GameManager.Instance.StartBack();
				CloseSelf();
            });

            BtnReplay.onClick.AddListener(() => {
    
    
                SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
            });

			BtnHome.onClick.AddListener(() => {
    
    
				UIKit.OpenPanel<StartGamePanel>();
                CloseSelf();
            });
        }
		
		protected override void OnOpen(IUIData uiData = null)
		{
    
    
		}
		
		protected override void OnShow()
		{
    
    
		}
		
		protected override void OnHide()
		{
    
    
		}
		
		protected override void OnClose()
		{
    
    
		}
	}
}

Obtener un recurso en el reloj QF

El nuevo ResLoader() es un prefabricado obsoleto de
la bola con efecto de explosión.

			//在扫雷案例中测试的,用到WhiteChess
			ResKit.Init();
            ResLoader loader = ResLoader.Allocate();
			GameObject prefab = loader.LoadSync<GameObject>("WhiteChess");
			Instantiate(prefab , transform);

Procesar GameManager en GamePanel

01 Primero refiera todos los scripts de los nodos secundarios al nodo principal GamePanel
02 Extraiga los nodos a los que se hace referencia en el script, cámbieles el nombre (igual que el nombre del nodo) y agregue el script Bind. Vaya a la parte superior de la secuencia de comandos para facilitar la visualización.
03 Debido a que se utiliza la interfaz de usuario, SpriteRenderer debe cambiarse a Imagen

Características del reloj Awake

Solo se usa el método Awake en el script, y no habrá ninguna opción de verificación delante de él.
inserte la descripción de la imagen aquí

error recurso AB no existe

Obviamente si, inténtalo de nuevo

error 3D a UGUI

Después de que SpriteRenderer transfiera la imagen (quiero usar el método de QF para llamar al panel), la bola se mueve muy poco.
El método usa la misma UIRoot antes de generar el archivo de mapa, es decir, UGUI, en lugar de las coordenadas mundiales originales. En este punto, tenga cuidado de ajustar Scale del nodo padre y RectTranfrom de la bola prefabricada Ball a 1, de lo contrario habrá problemas con la distancia entre las bolas (el problema es que hay un problema con la distancia entre las bolas, o las pistas no coinciden)

modificar imagen UGUI

3000 es la suavidad de la bola que se mueve a lo largo de la curva
. 0.3 también es equivalente al diámetro de la bola. Este diámetro es el diámetro de la bola prefabricada que desea instanciar.
inserte la descripción de la imagen aquí

El método usa la misma UIRoot antes de generar el archivo de mapa, es decir, UGUI, en lugar de las coordenadas mundiales originales. Al mismo tiempo, debe multiplicarse por el aumento (pruebe 230 es adecuado)

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

public class MapConfig : ScriptableObject
{
    
    
    public float EndPoint {
    
     get; private set; }

    public List<Vector3> pathPointList = new List<Vector3>();

    public void InitMapConfig()
    {
    
    
        EndPoint = pathPointList.Count - 2;
    }

    public Vector3 GetPosition(float progress)
    {
    
    
        Camera ui=Camera.main.gameObject.FindComponentWithTag<Camera>("UI");
        int index = Mathf.FloorToInt(progress);
         //return Vector3.Lerp(pathPointList[index], pathPointList[index + 1], progress - index);

        Vector3 v1 = Vector3.Lerp(pathPointList[index], pathPointList[index + 1], progress - index);

        return v1*230f;
    }

}

bola de seguimiento de efecto

inserte la descripción de la imagen aquí

-------------------------------------

modificar La posición de lanzamiento, la velocidad y el punto final de la bola de lanzamiento están fuera de los límites

donde se lanza la pelota

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

velocidad

inserte la descripción de la imagen aquí

Juicio más allá de los límites

Simplemente arrastre la bola en el lienzo hasta el límite del lienzo y mire las coordenadas
inserte la descripción de la imagen aquí

Efecto

inserte la descripción de la imagen aquí

-------------------------------------------

El tamaño y la posición del efecto de destrucción de errores.

using QFramework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ResLoader = QFramework.ResLoader;

public class FXManager :MonoSingleton<FXManager>
{
    
    
       Transform FXs;
   //
    GameObject destroyFXPrefab;
    ObjectPool<GameObject> destroyFXPool;
 

                                                                
    public void Init(Transform FXs)
    {
    
    
        this.FXs = FXs;
        //
        ResKit.Init();
        QFramework.ResLoader loader =  QFramework.ResLoader.Allocate();
        destroyFXPrefab = loader.LoadSync<GameObject>("DestroyFX"); 
        destroyFXPool = new ObjectPool<GameObject>(InstantiateFX, 10);
    }


    private GameObject InstantiateFX()
    {
    
    
        GameObject go = Instantiate(destroyFXPrefab, FXs);
        go.Hide();
        return go;
    }


    public void ShowDestroyFX(Vector3 pos)
    {
    
    
        GameObject go = destroyFXPool.GetObject();
        go.Show();
        go.transform.localPosition = pos;

        //延时0.5f执行回收操作
        ScheduleOnce.Start(this, () =>
         {
    
    
             go.Hide();
             destroyFXPool.AddObject(go);
         }, 0.5f);
    }
}

El emisor de errores gira una vez y se fija en la parte inferior izquierda.

Se hará automáticamente más tarde, ¿tal vez la llamada de bucle para abrir el GamePanel se haya cambiado, lo que resultó en múltiples GamePanels?
inserte la descripción de la imagen aquí

actualización automática de errores

Después de hacer clic varias veces, no hay respuesta porque no hubo una actualización automática
inserte la descripción de la imagen aquí

error Los tres mapConfigs no se pueden colocar en Recursos, y están en blanco cuando se generan

Si no coloca Recursos,
GameManager.Instance.mapConfig estará vacío después de ejecutarse. Esto se debe a que
algunos de los mapconfigArr en la clase pública GameSceneConfig: MonoSingleton están vacíos.

El bicho no es sensible al levantar el lanzamiento

cierra esto
inserte la descripción de la imagen aquí

reloj no retrocede despues de eliminar la bola

Es necesario retroceder tras la pequeña bola.Después
de la pequeña bola, todavía existe la situación de continuar eliminando la bola.

El error es demasiado difícil de retroceder después de la resurrección.

modificar SoundManager

Después de leer el ejemplo, no hay necesidad de una inicialización similar a ResKit.Init() de UIkit
AudioKit.PlaySound("resources://Sound/"+clipName);
AudioKit.PlayMusic("resources://Sound/"+name, volume:volume);

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using QFramework;

public class SoundManager : MonoSingleton<SoundManager>
{
    
    
    static AudioSource bgAudio;


    public void Init()
    {
    
    
        bgAudio = gameObject.GetOrAddComponent<AudioSource>();
    }


    private static void PlaySound(string clipName)
    {
    
    
      //  AudioSource.PlayClipAtPoint(GetAudioClip(clipName), Vector3.zero);
        AudioKit.PlaySound("resources://Sound/"+clipName );
    }


    public static AudioClip GetAudioClip(string clipName)
    {
    
    
        return Resources.Load("Sound/" + clipName, typeof(AudioClip)) as AudioClip;
    }


    public static void PlayDestroy() {
    
     PlaySound("Eliminate");  }
    public static void PlayShoot()   {
    
     PlaySound("Shoot"); }
    public static void PlayInsert()  {
    
     PlaySound("BallEnter"); }
    public static void PlayBomb()    {
    
     PlaySound("Bomb"); }
    public static void PlayFail()    {
    
     PlaySound("Fail"); }
    public static void PlayFastMove(){
    
     PlaySound("FastMove"); }
    public static void PlayMusic(string name,float volume=0.3f) 
    {
    
                                                       
        //bgAudio.clip = SoundManager.GetAudioClip(name);//*-
        //bgAudio.volume = volume;
        //bgAudio.loop = true;
        //bgAudio.Play();
        AudioKit.PlayMusic("resources://Sound/"+name,volume:volume);
    }



}

pérdida de datos bug shooterSO

Ocurrió que el Vector3 interior se perdió, por lo que se utilizó lo siguiente. no se si funciona o no

        EditorUtility.SetDirty(fromAsset);

inserte la descripción de la imagen aquí

Nombre del paquete AB del objeto de error

Originalmente nombré AB 0_mapconfig, y este ABbao1 también se incluyó en el paquete,
pero 0_asset apareció automáticamente a la derecha y el archivo se marcó automáticamente como 0)_asset, lo que provocó que 0_asset apareciera en el paquete posterior
inserte la descripción de la imagen aquí

Error La bola no se destruye después de pasar el siguiente nivel, pero progresa == 0

Esta es una sección de la inicialización inicial de la bola pequeña. No se mueve porque GmaeState==Succ en este momento. Para volver a ingresar al juego, GameState debe reiniciarse
inserte la descripción de la imagen aquí

modificar la división del administrador

Administrador dividido de GamePanel
inserte la descripción de la imagen aquí

--------------------------------------------------------

Descripción de los dos paneles del Panel

También lo genera automáticamente la secuencia de comandos de la interfaz de usuario de QF y el código se completa
. . . .
Hay demasiada reversión durante la resurrección (la razón de 3D a UGUI), y el valor debe ajustarse (hay un tiempo de reversión de 3 segundos)
. . . .
El efecto de los dos paneles se encuentra al final del artículo.

Éxito del panel

using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UnityEngine.SceneManagement;
using QFramework.PointGame;


namespace QFramework.Example
{
    
    
	public class SuccPanelData : UIPanelData
	{
    
    
	}
	public partial class SuccPanel : UIPanel
	{
    
    
		protected override void OnInit(IUIData uiData = null)
		{
    
    
			mData = uiData as SuccPanelData ?? new SuccPanelData();
			// please add init code here


			BtnNext.onClick.AddListener(() => {
    
    
				
				UIKit.OpenPanel<GamePanel>(
					new GamePanelData() {
    
     LevelCount=GameData.GetLevelIndex() }
				);
				CloseSelf();
			});

			BtnHome.onClick.AddListener(() => {
    
    
                UIKit.OpenPanel<StartGamePanel>();
                CloseSelf();
            });
        }
		
		protected override void OnOpen(IUIData uiData = null)
		{
    
    
		}
		
		protected override void OnShow()
		{
    
    
		}
		
		protected override void OnHide()
		{
    
    
		}
		
		protected override void OnClose()
		{
    
    
		}
	}
}

El panel falló

Lo principal es la resurrección, no puede ser Cerrar, así que después de fallar, Ocultar primero, luego
resucitar en 01, mostrar
02 nuevamente, cerrar y
regresar a la página de inicio en Abrir 03

using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UnityEngine.SceneManagement;

namespace QFramework.Example
{
    
    
	public class GameOverPanelData : UIPanelData
	{
    
    
	}


	public partial class GameOverPanel : UIPanel
	{
    
    
		protected override void OnInit(IUIData uiData = null)
		{
    
    
			mData = uiData as GameOverPanelData ?? new GameOverPanelData();
			// please add init code here

			BtnReset.onClick.AddListener(()=>{
    
     //复活
                GameManager.Instance.GameRevive();
                CloseSelf();

            });

            BtnReplay.onClick.AddListener(() => {
    
     //再来一次
                UIKit.ClosePanel<GamePanel>();
                UIKit.OpenPanel<GamePanel>( new GamePanelData() {
    
     LevelCount=GameData.GetLevelIndex() });
                CloseSelf();
            });

			BtnHome.onClick.AddListener(() => {
    
    	 //主页
                UIKit.ClosePanel<GamePanel>();
                UIKit.OpenPanel<StartGamePanel>();
                CloseSelf();
            });
        }
		
		protected override void OnOpen(IUIData uiData = null)
		{
    
    
		}
		
		protected override void OnShow()
		{
    
    
		}
		
		protected override void OnHide()
		{
    
    
		}
		
		protected override void OnClose()
		{
    
    
		}
	}
}

---------------------------------------------------------

Producción de pistas de herramientas

modificar BezierPathController

Haz la bola prefabricada (usé el sprite (UGUI) de la bola roja (puedes usar otros), el original es MeshRender (en el mundo 3D)) el nodo "Mapa" se usa en BezierPathController.Awake(), se usa para demostrar las coordenadas de la bola azul, puedes
comentarlo

01 Arrastre uno al nodo "1" (con el script BezierPathController)
01 Copie constantemente el prefabricado debajo del nodo con Ctrl+D (cada 4 (básicamente 2 controlan la curvatura, 2 en la pista) prefabricado de bola roja generará un pedazo de bola azul) 02 Lista de puntos de control contiene los datos de coordenadas de la bola roja (coordenadas mundiales). ", "Lista de puntos de ruta" es la posición de la bola azul (coordenadas mundiales) también guardado en la carpeta
05 Map


inserte la descripción de la imagen aquí

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

public class BezierPathController : MonoBehaviour
{
    
    

    #region 字属



    public int segmentsPerCurve = 3000;
    /// <summary>连线上求和球之间的举例,也就是比直径大一点</summary>
    public float BallAndBallDis = 0.3f;
    public bool Debug = true;
    public GameObject ballPrefab;

    /// <summary>贝塞尔曲线的节点。控制弯曲度的白球</summary>
    public List<GameObject> ControlPointList = new List<GameObject>();
    /// <summary>贝塞尔曲线的的线段。连线的蓝球的坐标</summary>
    public List<Vector3> pathPointList = new List<Vector3>();
    #endregion


    //private void Awake()
    //{
    
    
    //    Debug = true;
    //    foreach (var item in pathPointList)
    //    {
    
    
    //        GameObject ball = Instantiate(ballPrefab, GameObject.Find("Map").transform);
    //        ball.transform.position = item;
    //    }
    //}


    private void OnDrawGizmos()
    {
    
    
        //节点
        ControlPointList.Clear();
        foreach (Transform item in transform)//没错,就是遍历子节点
        {
    
    
            ControlPointList.Add(item.gameObject);
        }


        //线段
        List<Vector3> controlPointPos 
            = ControlPointList.Select(point => point.transform.position).ToList();
        var points = GetDrawingPoints(controlPointPos, segmentsPerCurve);

        Vector3 startPos = points[0];
        pathPointList.Clear();
        pathPointList.Add(startPos);
        for (int i = 1; i < points.Count; i++)
        {
    
    
            if (Vector3.Distance(startPos, points[i]) >= BallAndBallDis)
            {
    
    
                startPos = points[i];
                pathPointList.Add(startPos);
            }
        }

        foreach (var item in ControlPointList)
        {
    
    
            item.GetComponent<Image>().enabled = Debug;//相当于将物体隐身,并不会影响物体的脚本运行,物体的碰撞体也依然存在。
        }

        if (Debug == false)
        {
    
     
            return;
        } 


        //01 画连线球的球
        Gizmos.color = Color.blue;
        foreach (var pos in pathPointList)
        {
    
    
            Gizmos.DrawSphere(pos, BallAndBallDis / 2);
        }

        //02 画连线球的线
        Gizmos.color = Color.yellow;
        for (int i = 0; i < points.Count - 1; i++)
        {
    
    
            Gizmos.DrawLine(points[i], points[i + 1]);
        }

        //03 画连线球的的弯曲度控制线
        //绘制贝塞尔曲线控制点连线,红,色
        Gizmos.color = Color.red;
        for (int i = 0; i < controlPointPos.Count - 1; i++)
        {
    
    
            Gizmos.DrawLine(controlPointPos[i], controlPointPos[i + 1]);
        }

    }



    #region 辅助


    /// <summary>贝塞尔线段</summary>
    List<Vector3> GetDrawingPoints(List<Vector3> controlPoints, int segmentsPerCurve)
    {
    
    
        List<Vector3> points = new List<Vector3>();
        for (int i = 0; i < controlPoints.Count - 3; i += 3)
        {
    
    
            var p0 = controlPoints[i];
            var p1 = controlPoints[i + 1];
            var p2 = controlPoints[i + 2];
            var p3 = controlPoints[i + 3];

            for (int j = 0; j <= segmentsPerCurve; j++)
            {
    
    
                var t = j / (float)segmentsPerCurve;
                points.Add(CalculateBezierPoint(t, p0, p1, p2, p3));
            }
        }
        return points;
    }

    /// <summary>
    /// <summary>贝塞尔曲线的三次方公式</summary>
    /// </summary>
    /// <param name="t"></param>
    /// <param name="p0">起点</param>
    /// <param name="p1">一侧的平滑度调节点</param>
    /// <param name="p2">另一侧的平滑度调节点</param>
    /// <param name="p3">终点</param>
    /// <returns></returns>
    Vector3 CalculateBezierPoint(float t
        , Vector3 p0
        , Vector3 p1, Vector3 p2
        , Vector3 p3)
    {
    
    
        var x   = 1 - t;
        var xx  = x * x;
        var xxx = x * x * x;
        var tt  = t * t;
        var ttt = t * t * t;
        return p0 * xxx 
            +   3 * p1 * t * xx 
            +   3 * p2 * tt * x 
            +  p3 * ttt;
    }


#if UNITY_EDITOR
    /// <summary>
    /// pathPointList写入"Assets/Map/map.asset"
    /// 但没有覆盖功能,删掉再创建就看得见效果了
    /// </summary> 
    public void CreateMapAsset()
    {
    
    
        string assetPath =String.Format(  "Assets/Map/{0}.asset",gameObject.name);  //写这Vector3数据的
        MapConfig mapConfig = new MapConfig();
        foreach (Vector3 item in pathPointList)
        {
    
    
            mapConfig.pathPointList.Add(item);
        }
        AssetDatabase.CreateAsset(mapConfig, assetPath);
        AssetDatabase.SaveAssets();
    }
#endif


    #endregion


}


#if UNITY_EDITOR
[CustomEditor(typeof(BezierPathController))]
public class BezierEditor : Editor
{
    
    
    public override void OnInspectorGUI()
    {
    
    
        base.OnInspectorGUI();
        if (GUILayout.Button("生成地图文件"))//详情面板下的按钮
        {
    
    
            (target as BezierPathController).CreateMapAsset();
        }
        AssetDatabase.Refresh();
    }
}
#endif



modificar guardar ubicación, nombre de archivo

Si la ubicación de guardado se coloca en Recursos, se informará un error.
El nombre del archivo se cambia a gameObject.name, no está codificado.

string assetPath =String.Format( “Activos/Mapa/{0}.asset”, gameObject.name); //escribe estos datos de Vector3

el reloj atraviesa nodos secundarios

Transform implementa iteradores internamente, por lo que se puede escribir así

        //节点
        ControlPointList.Clear();
        foreach (Transform item in transform)//没错,就是遍历子节点
        {
    
    
            ControlPointList.Add(item.gameObject);
        }

Posición de Tool Frog Shooter

GameMapConfig para controlar, hay una matriz Vector3 dentro

modificar Modificar el nombre de la imagen (-1) para facilitar la correspondencia

inserte la descripción de la imagen aquí

modificar Una herramienta para hacer posiciones de tirador

/****************************************************
    文件:MakeShooterPos.cs
	作者:lenovo
    邮箱: 
    日期:2023/7/19 15:37:17
	功能:
*****************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Random = UnityEngine.Random;
 

public class MakeShooterPos : MonoBehaviour
{
    
    
#if UNITY_EDITOR
    /// <summary>
    /// pathPointList写入"Assets/Map/map.asset"
    /// 但没有覆盖功能,删掉再创建就看得见效果了
    /// </summary> 
    public void RecordeShooterPos()
    {
    
    
        MapConfig fromAsset= AssetDatabase.LoadAssetAtPath<MapConfig>("Assets/Map/shooter.asset");
        int idx = int.Parse( gameObject.name);
        Transform shooter = GameObject.Find("ShooterTrans").transform;
        fromAsset.pathPointList[idx] = shooter.localPosition;
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }
#endif

}

#if UNITY_EDITOR
[CustomEditor(typeof(MakeShooterPos))]
public class MakeShooterPosEditor : Editor
{
    
    
    public override void OnInspectorGUI()
    {
    
    
        base.OnInspectorGUI();
        if (GUILayout.Button("生成Shooter位置"))//详情面板下的按钮
        {
    
    
            (target as MakeShooterPos).RecordeShooterPos();
        }
        AssetDatabase.Refresh();
    }
}
#endif





Efecto

inserte la descripción de la imagen aquí

---------------------------------------------------------

efecto global

01 Presione principalmente la tecla S (Éxito) para pasar rápidamente el nivel y la prueba.
02 Presione principalmente la tecla F (Fallo) para fallar rápidamente y probar.
Los datos del mapa solo se han probado en tres niveles, por lo que se informa un error al final.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_39538253/article/details/131519015
Recomendado
Clasificación