Información util para Unity
-
-
Save edwrodrig/34b667e021b2552013abe707f458eccb to your computer and use it in GitHub Desktop.
Última fecha: 2023-09-24
Última fecha: 2023-09-24
- Menú
Edit > Project Settings > Editor
enAny Android Device
. - Menú
Build Settings
. CambiarPlatform
aAndroid
. Instalar con botónInstall with Unity Hub
si es necesario. - Revisar que dispositivo Android tenga
depuración USB
activada y el modo de conexión esté entransferencia de archivos
. - Adicionalmente se puede revisar por consola la conexión con el comando
adb devices
.
Última fecha: 2023-09-24
- Menú
File > Package Manager
. - En menú
Packages
elegirUnity Registry
. - En el input buscar escribir
Recorder
- Pulsar
Install
Última fecha: 2023-09-24
- Menú
Window > General > Recorder Window
- Presionar
Add recorder
y seleccionarMovie
.
Última fecha: 2023-09-24
O como hacer strings
como printf
. Más detalles en el siguiente link
var name = "Mark";
var date = DateTime.Now;
// Composite formatting:
Console.WriteLine("Hello, {0}! Today is {1}, it's {2:HH:mm} now.", name, date.DayOfWeek, date);
// String interpolation:
Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.");
// Both calls produce the same output that is similar to:
// Hello, Mark! Today is Wednesday, it's 19:40 now.
Última fecha: 2023-09-24
- Arrastrar una imagen desde el explorador de archivos a la pantalla de
Projects
. - Seleccionar la imagen y en
Inspector
presionarSprite Editor
. - Cambiar modo a
Skinning Editor
. - Presionar
Auto Geometry
para generar geometría del personaje. - Crear huesos con
Create Bone
. - Apretar
Visibility
para revisar la jerarquía y propiedades de cada hueso. - Apretar
Auto Weights
para dar una influencia de los huesos sobre la geometría.
Última fecha: 2023-09-24
- Arrastrar el
Sprite
a la escena. Debería agregar ungame object
con unSprite Renderer
con alsprite
referenciado. - En el
Inspector
, presionarAdd Component > 2D Animation > Sprite Skin
. - En el componente
Sprite Skin
, presionarCreate Bones
. Debería agregar huesos algame object
. Los huesos se puede animar como cualquier otro objeto.
Última fecha: 2023-09-24
En este link muestra el orden de ejecución (Execution order
) que tiene el game loop
.
Última fecha: 2023-09-24
Estas variables pueden ser utilizadas en los métodos update. Para más información ver el siguiente link.
Time.fixedDeltaTime
: siempre es igual. Marca el tiempo del intervalo de lafísica
.Time.fixedTime
: es el tiempo en que ocurrió el últimpfixedTime
.Time.timeSinceLevelLoad
: el tiempo desde que se cargó la escena.Time.time
: es el tiempo absoluto, o tiempo de reloj.
Última fecha: 2023-09-24
- Corutina
WaitForFixedUpdate
. link
Última fecha: 2023-09-24
Este script convierte un objeto de draggeable mediante un touch
using UnityEngine;
public class TouchControl : MonoBehaviour
{
private Vector3 offset;
private Camera mainCamera;
private bool dragging;
void Start()
{
mainCamera = Camera.main;
}
void Update()
{
// si hay más de un toque
// recordar que s pantallas son multitouch y pueden tener más de un toque
if (Input.touchCount > 0)
{
//obtener el primer toque, 0 indica el primero, 1 el segundo y así consecutivamente
Touch touch = Input.GetTouch(0);
//si tocamos la pantalla
if (touch.phase == TouchPhase.Began)
{
//convertir una posicion de la pantalla a una posicion del mundo
Vector3 touchPosition = mainCamera.ScreenToWorldPoint(touch.position);
//elimina la profundidad, estamos en un juego 2D
touchPosition.z = 0;
//calculamos desde donde empezamos a considerar el movimiento
//offset tendra la posicion inicial del objeto menos donde empezamos a mover el dedo
offset = transform.position - touchPosition;
//marcamos que vamos a empezar un arrastre
dragging = true;
}
//si estamos moviendo nuestro dedo y hemos marcado que empezamos el arrase
if (touch.phase == TouchPhase.Moved && dragging)
{
//convertir una posicion de la pantalla a una posicion del mundo
Vector3 touchPosition = mainCamera.ScreenToWorldPoint(touch.position);
//elimina la profundidad, estamos en un juego 2D
touchPosition.z = 0;
//actualizamos la posicion
transform.position = touchPosition + offset;
//fit in the screen
Vector3 pos = mainCamera.WorldToViewportPoint (transform.position);
pos.x = Mathf.Clamp01(pos.x);
pos.y = Mathf.Clamp01(pos.y);
transform.position = mainCamera.ViewportToWorldPoint(pos);
}
if (touch.phase == TouchPhase.Ended)
{
dragging = false;
}
}
}
}
Para cargar una escena de forma rápida, utilizar el siguiente script.
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneSwitcher : MonoBehaviour
{
public void LoadScene(string sceneName)
{
SceneManager.LoadScene(sceneName);
}
}
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class LoadingSceneController : MonoBehaviour
{
public Slider progressBar; // Referencia al componente Slider (Barra de progreso)
// Método para iniciar la carga de la escena
public void LoadScene(string sceneName)
{
StartCoroutine(LoadSceneAsync(sceneName));
}
private IEnumerator LoadSceneAsync(string sceneName)
{
// Inicia la carga de la escena de manera asíncrona
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneName);
// Evita que la escena se active automáticamente al terminar la carga
asyncOperation.allowSceneActivation = false;
while (!asyncOperation.isDone)
{
// Actualiza la barra de progreso
float progress = Mathf.Clamp01(asyncOperation.progress / 0.9f);
progressBar.value = progress;
// Checa si la escena ha terminado de cargar (el valor de progress llega hasta 0.9)
if (asyncOperation.progress >= 0.9f)
{
// Activa la escena cuando esté lista
asyncOperation.allowSceneActivation = true;
}
yield return null;
}
}
}
``
public class Mover : MonoBehaviour
{
public float speed = 5f;
void Update()
{
Vector3 left = new Vector3(-1, 0, 0);
transform.Translate(left * speed * Time.deltaTime, Space.World);
}
}
- Ambos objetos tienen que tener un
Collider 2D
. - Uno objeto debe tener un
Rigid Body 2D
. - Uno o ambos objetos deben tener un script con
OnCollisionEnter2D
.
Edit -> Project Settings -> Physics 2D.
public class EnemyCollider : MonoBehaviour
{
void OnCollisionEnter2D(Collision2D collision)
{
//get name of gameObject
string name = collision.gameObject.name;
Debug.Log("Collision detected enemy: " + name);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyCollider : MonoBehaviour
{
public int health = 10;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void OnCollisionEnter2D(Collision2D collision)
{
//get name of gameObject
string name = collision.gameObject.name;
Debug.Log("Collision detected enemy: " + name);
}
void OnTriggerEnter2D(Collider2D other)
{
//get name of gameObject
string tag = other.gameObject.tag;
if (tag == "bullet")
{
Destroy(other.gameObject);
Debug.Log("Bullet destroyed");
health--;
if (health <= 0)
{
//change the parameter of the current animator state machine
GetComponent<Animator>().SetBool("isAlive", false);
}
}
}
void ExplodeFinished() {
Debug.Log("Exploded Finished");
Destroy(gameObject);
}
}
public class CoroutineAnimation : MonoBehaviour
{
public Vector3 targetPosition;
public float duration = 2.0f;
private void Start()
{
StartCoroutine(AnimateToPosition(transform, targetPosition, duration));
}
private IEnumerator AnimateToPosition(Transform transform, Vector3 target, float duration)
{
float startTime = Time.time;
Vector3 startPosition = transform.position;
while (Time.time < startTime + duration)
{
float t = (Time.time - startTime) / duration;
transform.position = Vector3.Lerp(startPosition, target, t);
yield return null; // Wait for the next frame
}
transform.position = target; // Ensure the final position is set accurately
}
}
Pillarbox vs Letterbox
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScreenAdjust : MonoBehaviour
{
public float targetWidth = 1080f;
public float targetHeight = 1920f;
public float pixelPerWorldUnits = 10.0f;
[Tooltip("La camara que se va a ajustar")]
public Camera camera;
// determine the game window's current aspect ratio
//es mayor entre mas ancho sea
public float GetWindowAspect() {
return (float)Screen.width / (float)Screen.height;
}
// desired aspect ratio
// es mayor entre mas ancho sea
public float GetTargetAspect() {
return targetWidth / targetHeight;
}
public float GetScaleHeight() {
return (float)Screen.height / targetHeight;
}
public float GetScaleWidth() {
return (float)Screen.width / targetWidth;
}
public Rect GetPillarBoxRect() {
float scaleHeight = GetScaleHeight();
Rect rect = new Rect();
rect.width = GetScaleHeight();
rect.height = 1.0f;
rect.x = (1.0f - rect.width) / 2.0f;
rect.y = 0;
return rect;
}
public Rect GetLetterBoxRect() {
float scaleWidth = GetScaleWidth();
Rect rect = new Rect();
//en letter box el ancho es el mismo que la pantalla
rect.width = 1.0f;
//pero el alto es menor
rect.height = GetScaleHeight();
rect.x = 0;
rect.y = (1.0f - rect.height) / 2.0f;
return rect;
}
public bool ShouldBeLetterBox() {
// si la pantalla es menos ancha que la esperada
return GetWindowAspect() < GetTargetAspect();
}
public bool ShouldBePillarBox() {
return !ShouldBeLetterBox();
}
public void AdjustCameraToScreen() {
if (camera == null) {
Debug.LogError("Camera should be set");
return;
}
if (ShouldBeLetterBox()) {
var newTargetHeight = (float)Screen.height / (float)Screen.width * targetWidth;
Debug.Log("LetterBox");
camera.orthographicSize = (newTargetHeight / pixelPerWorldUnits) / 2.0f;
} else {
var newTargetHeight = targetHeight;
Debug.Log("PillarBox");
camera.orthographicSize = (newTargetHeight / pixelPerWorldUnits) / 2.0f;
}
}
[ContextMenu("Set Camera Default Parameters")]
public void SetCameraDefaultParams() {
if (camera == null) {
Debug.LogError("Camera should be set");
return;
}
camera.orthographic = true;
camera.orthographicSize = (targetHeight / pixelPerWorldUnits) / 2.0f;
camera.nearClipPlane = -0.3f;
camera.farClipPlane = 1000.0f;
camera.transform.position = new Vector3(
(targetWidth / pixelPerWorldUnits) / 2.0f,
(targetHeight / pixelPerWorldUnits) / 2.0f,
0);
}
void Start()
{
AdjustCameraToScreen();
}
}
``
using UnityEngine;
using UnityEngine.Events;
using UnityEditor;
public class Waypoint : MonoBehaviour
{
#if UNITY_EDITOR
//draw as a cross in editor mode
void OnDrawGizmos()
{
Gizmos.color = Color.yellow;
//draw cross with lines
Gizmos.DrawLine(transform.position + new Vector3(-5f, 0, 0), transform.position + new Vector3(5f, 0, 0));
Gizmos.DrawLine(transform.position + new Vector3(0, -5f, 0), transform.position + new Vector3(0, 5f, 0));
//draw label
Handles.Label(transform.position + new Vector3 (1.0f, -1.0f, 0), gameObject.name);
}
#endif
}
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
using System;
[Serializable]
public class DelayedEvent {
public float delay;
public UnityEvent action;
public IEnumerator Invoke() {
yield return new WaitForSeconds(delay);
action.Invoke();
}
}
public class TriggerArea : MonoBehaviour
{
public DelayedEvent[] onLanderPass;
public DelayedEvent[] onBecameVisible;
Collider2D landerCollider;
public bool disabled = false;
void Awake() {
landerCollider = GetComponent<Collider2D>();
}
private void OnTriggerEnter2D(Collider2D other) {
if ( disabled )
return;
if(other.gameObject.tag == "Player")
{
foreach (var e in onLanderPass) {
StartCoroutine(e.Invoke());
disabled = true;
}
} else if ( other.gameObject.tag == "Camera" ) {
foreach ( var delayedEvent in onBecameVisible ) {
StartCoroutine(delayedEvent.Invoke());
disabled = true;
}
}
}
void OnDrawGizmos() {
Gizmos.color = Color.green;
//get offset
var collider = GetComponent<Collider2D>();
var center = transform.position - collider.bounds.center;
Gizmos.DrawWireCube(center, collider.bounds.size);
}
}
Los resource tienes que estar en la carpeta Resources
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Blinker : MonoBehaviour
{
[HideInInspector]
public Animator animator;
private AudioSource bubbleAudioSource;
private AudioSource burstAudioSource;
public AudioClip customBurstSound;
void Awake() {
animator = GetComponent<Animator>();
}
void Start()
{
bubbleAudioSource = gameObject.AddComponent<AudioSource>();
bubbleAudioSource.clip = Resources.Load<AudioClip>("Sounds/bubble");
burstAudioSource = gameObject.AddComponent<AudioSource>();
if ( customBurstSound != null ) {
burstAudioSource.clip = customBurstSound;
} else {
burstAudioSource.clip = Resources.Load<AudioClip>("Sounds/score");
}
}
}
Persistent Data Path mas informacion
Some issues Json serialization problem
Serializaició de Dicts en JSON request
using System;
using System.IO;
using UnityEngine;
public class AppDataStorage : MonoBehaviour {
public AppData appData;
public string getPath() {
return Application.persistentDataPath + "/appData.json";
}
public void LoadGame()
{
string path = getPath();
if ( !File.Exists(getPath()) ) {
Debug.Log("No existe el archivo [" + path + "]");
appData = new AppData();
return;
}
string jsonData = File.ReadAllText(getPath());
appData = JsonUtility.FromJson<AppData>(jsonData);
Debug.Log("Loaded game" + jsonData + " from " + path);
}
public void SaveGame() {
string path = getPath();
string jsonData = JsonUtility.ToJson(appData);
File.WriteAllText(path , jsonData);
Debug.Log("Saved game" + jsonData + " to " + path);
}
public static T LoadFile<T>(string path) {
if ( !File.Exists(path) ) {
Debug.Log("No existe el archivo [" + path + "]");
return default(T);
}
string jsonData = File.ReadAllText(path);
T data = JsonUtility.FromJson<T>(jsonData);
Debug.Log("Loaded game" + jsonData + " from " + path);
return data;
}
public static void SaveFile<T>(string path, T data) {
string jsonData = JsonUtility.ToJson(data);
File.WriteAllText(path , jsonData);
Debug.Log("Saved game" + jsonData + " to " + path);
}
}
Serializable data
using System;
using UnityEngine;
using System.Collections.Generic;
[Serializable]
public class LanderData {
public string landerId = "audacia";
public int numberCompleted = 0;
public int currentPoints = 0;
public int numberSpecies = 0;
public string currentRadar = null;
public string currentSensor = null;
public string currentSampler = null;
public bool visibleRadius = false;
[NonSerialized]
public LanderDataStatic dataStatic;
public LanderData() {}
public int GetUnlockLevel() {
return dataStatic.unlockLevel;
}
public string GetLanderId() {
return landerId;
}
public int GetLives() {
return dataStatic.lives;
}
public string GetLanderName() {
return dataStatic.landerName;
}
public BaseProgress GetLevelProgress() {
return new BaseProgress(currentPoints);
}
public string GetLanderDescription() {
return "Resistencia: " + dataStatic.lives;
}
public string GetUnlockablePortraitPath() {
return "Sprites/Pictures/lander/lander_" + GetLanderId() + "/sprite";
}
public string GetLanderSprite() {
return "Sprites/Pictures/lander/lander_" + GetLanderId() + "/sprite";
}
}
using UnityEngine;
using System;
using System.Linq;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
public class EnemyBehaviour : MonoBehaviour
{
public enum Type
{
GoToTarget,
GoToTargetNoRotate,
RotateAndGoToTarget,
Turn,
Rotate,
GoToStart,
Stay,
Repeat
}
[System.Serializable]
public class WaypointParam
{
public float duration;
public Type type;
public GameObject target;
public bool smooth = true;
public int value;
}
public WaypointParam[] waypointParamList;
public Vector3 startPosition;
public Enemy graphics;
public int repetitions = 1;
public bool clearAtEnd = false;
public List<WaypointParam> GetWaypointParamList() {
return waypointParamList.ToList();
}
public void SlotStart() {
if ( !graphics.gameObject.activeSelf ) {
graphics.gameObject.SetActive(true);
}
graphics.SetBehaviour(this);
graphics.SetCullUpdateTransform(true);
StartCoroutine(StartMovement());
}
IEnumerator StartGoToStart(WaypointParam param) {
if ( graphics == null ) {
yield break;
}
Vector3 startPosition = transform.position;
Vector3 endPosition = this.startPosition;
float startTime = Time.time;
graphics?.SlotChangeOrientation(endPosition.x - startPosition.x);
while (Time.time - startTime < param.duration)
{
float t = (Time.time - startTime) / param.duration;
if ( param.smooth ) {
t = Mathf.SmoothStep(0.0f, 1.0f, t);
}
transform.position = Vector3.Lerp(startPosition, endPosition, t);
yield return null;
}
}
IEnumerator StartGoToTarget(WaypointParam param) {
if ( graphics == null ) {
yield break;
}
Vector3 startPosition = transform.position;
Vector3 endPosition = param.target.transform.position;
float startTime = Time.time;
graphics?.SlotChangeOrientation(90 - (endPosition.x - startPosition.x) );
while (Time.time - startTime < param.duration)
{
float t = (Time.time - startTime) / param.duration;
if ( param.smooth ) {
t = Mathf.SmoothStep(0.0f, 1.0f, t);
}
transform.position = Vector3.Lerp(startPosition, endPosition, t);
yield return null;
}
}
IEnumerator StartGoToTargetNoRotate(WaypointParam param) {
if ( graphics == null ) {
yield break;
}
Vector3 startPosition = transform.position;
Vector3 endPosition = param.target.transform.position;
float startTime = Time.time;
while (Time.time - startTime < param.duration)
{
float t = (Time.time - startTime) / param.duration;
if ( param.smooth ) {
t = Mathf.SmoothStep(0.0f, 1.0f, t);
}
transform.position = Vector3.Lerp(startPosition, endPosition, t);
yield return null;
}
}
IEnumerator StartRotate(WaypointParam param) {
if ( graphics == null ) {
yield break;
}
var startPosition = graphics.transform.rotation;
var endPosition = param.target.transform.rotation;
float startTime = Time.time;
while (Time.time - startTime < param.duration)
{
float t = (Time.time - startTime) / param.duration;
if ( param.smooth ) {
t = Mathf.SmoothStep(0.0f, 1.0f, t);
}
graphics.transform.rotation = Quaternion.Lerp(startPosition, endPosition, t);
yield return null;
}
}
IEnumerator StartRotateAndGoToTarget(WaypointParam param) {
if ( graphics == null ) {
yield break;
}
{
var startPosition = graphics.transform.rotation;
var endPosition = param.target.transform.rotation;
float startTime = Time.time;
while (Time.time - startTime < 1.0f)
{
float t = (Time.time - startTime) / 1.0f;
if ( param.smooth ) {
t = Mathf.SmoothStep(0.0f, 1.0f, t);
}
graphics.transform.rotation = Quaternion.Lerp(startPosition, endPosition, t);
yield return null;
}
}
{
Vector3 startPosition = transform.position;
Vector3 endPosition = param.target.transform.position;
float startTime = Time.time;
while (Time.time - startTime < (param.duration - 1.0f))
{
float t = (Time.time - startTime) / (param.duration - 1.0f);
if ( param.smooth ) {
t = Mathf.SmoothStep(0.0f, 1.0f, t);
}
transform.position = Vector3.Lerp(startPosition, endPosition, t);
yield return null;
}
}
}
IEnumerator StartTurn(WaypointParam param) {
if ( graphics == null ) {
yield break;
}
graphics.FlipHorizontallyIngame();
yield return null;
}
IEnumerator StartStay(WaypointParam param) {
yield return new WaitForSeconds(param.duration);
}
IEnumerator StartMovement() {
for ( int i = 0 ; i < repetitions ; i++ ) {
foreach ( WaypointParam waypointParam in GetWaypointParamList() ) {
switch ( waypointParam.type ) {
case Type.GoToStart:
yield return StartGoToStart(waypointParam);
break;
case Type.GoToTarget:
yield return StartGoToTarget(waypointParam);
break;
case Type.Stay:
yield return StartStay(waypointParam);
break;
case Type.Turn:
yield return StartTurn(waypointParam);
break;
case Type.GoToTargetNoRotate:
yield return StartGoToTargetNoRotate(waypointParam);
break;
case Type.Rotate:
yield return StartRotate(waypointParam);
break;
case Type.RotateAndGoToTarget:
yield return StartRotateAndGoToTarget(waypointParam);
break;
}
}
}
graphics?.SetCullUpdateTransform(false);
if ( clearAtEnd ) {
graphics?.SlotClear();
}
}
}
FIle > Build Settings > Player Settings > Player > Other Settings > Identification File > Build Settings > Build App Bundle (Google Play) Unity logs
https://discussions.unity.com/t/how-to-approach-analyzing-apk-size/206478