Permítanme primero explicar el escenario de lo que estoy tratando de hacer. Estoy tratando de crear un juego similar a VN donde los personajes cambian su imagen según la hora del día. Entonces, por ejemplo, durante el día entre las 8:00 a. m. y las 11:00 a. m., el personaje npc llamado Benjamin estaría de pie junto al estanque en la escena y después de las 11:00 a. m. se sentaría junto a la fogata en la escena. Esto significa que cada personaje NPC tiene muchos sprites/imágenes diferentes, pero solo uno de ellos debe activarse según la hora del día.
Quiero seguir las mejores prácticas cuando se trata de codificar y estructurar cómo funcionan mis scripts. Así que no quiero algo que funcione pero que esté hecho de manera desordenada y siento que podría mejorarse. Así es como lo hice:
public class Benjamin : MonoBehaviour { public GameObject BenjaminStanding; public GameObject BenjaminSitting; void Update() { //If Time logic Between 8:00AM - 11:00AM ActivateBenjaminStanding(); //if Time logic is After 11:00AM ActivateBenjamindSitting(); } //Activate Benjamin standing image public void ActivateBenjaminStanding() { BenjaminSitting.SetActive(false); BenjaminStanding.SetActive(true); } //Activate Benjamin sitting image public void ActivateBenjamindSitting() { BenjaminStanding.SetActive(false); BenjaminSitting.SetActive(true); } }En mi jerarquía tengo el gameobject Benjamin vacío y luego todas las imágenes debajo de ese objeto principal así:
Benjamín
Adjunto el script a mi objeto Benjamin y hago todas las referencias de imagen necesarias.
Ahora el código anterior funciona, pero siento que esta es una forma muy complicada de hacer las cosas, porque si tengo más personajes, tengo que hacer scripts individuales para cada personaje, algunos pueden tener pocas imágenes, otros pueden tener muchas. Y tengo que crear un método para cada imagen al activarlas. Entonces, ¿hay una mejor manera de hacer esto?
Estoy buscando algo más rápido, limpio y eficiente. Agradecería mucho cualquier ayuda o consejo. ¡Gracias!
Puedes crear una clase base para tus personajes. Conviértalo en una clase abstracta y agregue variables y métodos que todos los personajes deberían tener.
Me gusta
public abstract class Character : MonoBehaviour { public GameObject characterStanding; public GameObject characterSitting; internal virtual void Update() { //If Time logic Between 8:00AM - 11:00AM ActivateCharacterStanding(); //if Time logic is After 11:00AM ActivateCharacterSitting(); } //Activate Benjamin standing image public void ActivateCharacterStanding() { characterSitting.SetActive(false); characterStanding.SetActive(true); } //Activate Benjamin sitting image public void ActivateSitting() { characterStanding.SetActive(false); characterSitting.SetActive(true); } }Luego puede crear una subclase y heredar de la clase de caracteres.
public class Benjamin : Character { } public class Marting: Character { } public class John: Character { // You can change main class function and override it override Update(){ // If you remove this doesn't apply base class function. base.ActivateCharacter();} }
Pero si todos los personajes tienen propiedades similares y creas muchos de ellos, este enfoque no es útil en absoluto. Puede usar el objeto programable , puede crear activos para cada personaje y asignar el objeto programable al objeto de escena o prefabricado, elija la forma que sea mejor para su configuración.
Puede disminuir su trabajo organizando sus GameObjects en una estructura de datos y usando una sola función para cambiar entre imágenes.
Al hacerlo, puede generalizar su clase Benjamin en una clase de propósito más general para cualquier carácter dado, lo que le da a su componente reutilización.
Este ejemplo utiliza un Dictionary para organizar cada GameObject por su nombre y supone que cada imagen comparte el mismo nombre que el GameObject, de modo que se pueda hacer referencia al GameObject previsto por su nombre. De esta forma, en lugar de escribir variables para cada imagen y escribir un método para cada una de ellas, podemos llamar a una sola función (ej: Activate("BenjaminStanding") ).
public class ClassNameHere : MonoBehaviour { public GameObject[] images; private Dictionary<string, GameObject> imageDict; private GameObject currentImage; void Awake() { imageDict = new Dictionary<string, GameObject>(); foreach (GameObject image in images) { imageDict.Add(image.name, image); } } void Activate(string name) { if (currentImage) currentImage.SetActive(false); var image = imageDict[name]; image.SetActive(true); currentImage = image; } void Update() { //If Time logic Between 8:00AM - 11:00AM Activate("BenjaminStanding"); //if Time logic is After 11:00AM Activate("BenjaminSitting"); } }Si tiene muchas imágenes para cada una, lo más común es tener una variable de inspector que sea una matriz,
public ImageOrSomething[] avatars;Tenga en cuenta que luego, en el Inspector , puede colocar tantas imágenes como desee, sin ningún cambio en el código.
Tenga en cuenta que cuando digo "Imagen o algo" podría ser cualquier cosa... una Texture , una Image , un personaje animado completo, alguna hoja de sprites... lo que sea en su situación.
Más lejos...
De hecho, puede simplemente organizar las imágenes en su carpeta de Recursos y cargarlas por nombre .
De esa manera, cuando su departamento de diseño crea o cambia imágenes, o agrega diferentes tiempos, no realiza cambios en el código.
Aquí hay una especie de ejemplo aleatorio de cargar una textura en una tarjeta (piense en jugar a las cartas, digamos),
private int _Cardnumber = 1; public int Cardnumber { get { return _Cardnumber; } set { .. obviously check for valid numbers, etc string f = "bonuscards/bonus_" + Cardnumber.ToString(); Texture t = Resources.Load(f, typeof(Texture)) as Texture; ri.texture = t; } }En el ejemplo, las imágenes serían nombradas por su departamento de arte "bonus_3.png" "bonus_4.png" y así sucesivamente.
Además, puede determinar automáticamente qué elementos se encuentran en esa carpeta y elegir uno al azar (o cualquiera que sea el caso).
La forma inteligente de hacerlo es simplemente tener los tiempos reales en el nombre de la imagen.
Entonces algo como
cat_03.png cat_09.png cat_13.pngsignificaría que cambias a esas imágenes a las 0300, 0900 y 1300 respectivamente.
Digamos que desea agregar uno nuevo para el gato dormido y desea que suceda a las 10 p.m. Todo lo que haces es agregar la nueva imagen,
cat_22.pngsimplemente colóquelo en su carpeta de recursos y es automático desde allí.