1.Compression(壓縮質量):可以改為None,不壓縮的效果最好,但占用內存
2.Filter Mode(過濾模式):可以選擇Point(no filter)
3.Pixels Per Unit:是每個方格所容納的像素個數
4.切割圖集要選擇Sprite Mode 為 Multiple
注:Pivot(錨點)也就是圖片中心軸
5.在Preferences中的Tile Palette中可以添加更多快捷功能。
6.在animator中的每個animation,可以點擊Add Behaviour可以創建該類腳本,進行代碼控制。
7.動畫腳本寫設置動畫的函數,然后用其他腳本中調用,Trigger單獨調用,Int/float/bool在動畫腳本的update中更新。
8.Layer Override Priority是代表碰撞優先級,越高越會優先碰撞。
9.關于數值一般需要兩個:maxValue與currentValue。
10.繼承關系的父類可以寫成虛函數,通過子類進行覆寫。
public virtual void Move()
{//父類方法
}
override public void Move()
{base.Move();//依然使用父類中的方法,只是增加新的//子類覆寫方法
}
11.如果只是在子父之間使用的變量可以使用protected修飾符?。
12.如果合并的碰撞體無法檢測,可以調整Composite Collider 2D中Geometry Type為Polygons。
13.自動添加必需的組件添加可以使用:
[RequireComponent(typeof(Rigidbody2D))]
14.cinemachine中的confiner2D每次獲取都需要清理緩存(InvalidateCache)
15.多設備的管理需要使用InputSystem庫中的方法進行操作。
16.管理者一般只有一個,被管理者有多個。
17.調用不同物體的相同接口執行不同方法,接口中的方法不需要實現。
18.使用SO寫的事件,可以使用激活UnityEvent的方式來呼叫執行事件。
19.攻擊執行邏輯
????????1)Attack(攻擊者)
public class Attack : MonoBehaviour
{public int damage;public float attackRange;public float attackRate;//攻擊頻率private void OnTriggerStay2D(Collider2D other){other.GetComponent<Character>()?.TakeDamage(this);}
}
? ? ? ? 2)Character(被攻擊者)
public void TakeDamage(Attack attacker)
{if (currentHealth - attacker.damage > 0){currentHealth -= attacker.damage;}else{currentHealth = 0;}
}
具體邏輯:實際執行血量減少邏輯實在被攻擊者中,攻擊者主要起到通知的作用。?
20.數據保存邏輯
? ? ? ? 1)保存接口(需要保存數據的代碼調用接口)
public interface ISaveable
{DataDefination GetDataID();void RegisterSaveData(){DataManager.instance.RigisterSaveData(this);} void UnRegisterSaveData() => DataManager.instance.UnRegisterSaveData(this);void GetSaveData(Data data);void LoadData(Data data);
}
? ? ? ? 2)?數據管理者
public class DataManager : MonoBehaviour
{public static DataManager instance;[Header("事件監聽")]public VoidEventSO saveDataEvent;public VoidEventSO loadDataEvent;private List<ISaveable> saveableList = new ();private Data saveData;private void Awake(){if(instance == null)instance = this;elseDestroy(gameObject);saveData = new Data();}private void Update(){if (Keyboard.current.lKey.wasPressedThisFrame){Load();}}private void OnEnable(){saveDataEvent.OnEventRaised += Save;loadDataEvent.OnEventRaised += Load;}private void OnDisable(){saveDataEvent.OnEventRaised -= Save;loadDataEvent.OnEventRaised -= Load;}public void RigisterSaveData(ISaveable saveable){if (!saveableList.Contains(saveable)){saveableList.Add(saveable);}}public void UnRegisterSaveData(ISaveable saveable){saveableList.Remove(saveable);}public void Save(){foreach (var saveable in saveableList){saveable.GetSaveData(saveData);}foreach (var item in saveData.characterPosDict){Debug.Log(item.Key + " : " + item.Value);}}public void Load(){foreach (var saveable in saveableList){saveable.LoadData(saveData);}}
}
? ? ? ? 3)?數據唯一識別ID
public class DataDefination : MonoBehaviour
{public PersistentType persistentType;public string ID;private void OnValidate(){if (persistentType == PersistentType.ReadWrite){if(ID == string.Empty)ID = System.Guid.NewGuid().ToString();}else{ID = string.Empty;}}
}
? ? ? ? 4)數據
public class Data
{public string sceneToSave;public Dictionary<string,Vector3> characterPosDict = new ();public Dictionary<string,float> floatSaveData = new ();public GameSceneSO GetSaveScene(){var newScene = ScriptableObject.CreateInstance<GameSceneSO>();return newScene;}
}
?具體邏輯:一個腳本需要數據保存與讀取,需要調用接口,實現里面的方法并且注冊(卸載)注
? ? ? ? ? ? ? ? ? ?冊表,然后管理者在數據保存和加載時一次調用注冊表里的對象執行每個里面對應的
? ? ? ? ? ? ? ? ? ?保存與加載方法。
? ? ? ? ? ? ? ? ? ?數據會存入Data的每個字典中,每個字典分別由ID與存儲數據構成,那么每個腳本掛
? ? ? ? ? ? ? ? ? ?載的物體都需要生成唯一可識別ID。
21.Addressable的異步加載
????????1.場景切換管理
public Transform playerTrans;public Vector3 firstPosition;public Vector3 menuPosition;[Header("場景")]public GameSceneSO firstLoadScene;public GameSceneSO menuScene;[Header("事件廣播")]public VoidEventSO afterSceneLoadedEvent;public FadeEventSO fadeEvent;public SceneLoadEventSO unLoadedEvent;public GameSceneSO currentloadScene;private GameSceneSO sceneToLoad;private Vector3 posToGo;private bool isLoading;private void OnBackToMenuEvent(){sceneToLoad = menuScene;loadEventSO.RaiseLoadRequestEvent(sceneToLoad,menuPosition,true);}private void NewGame(){sceneToLoad = firstLoadScene;loadEventSO.RaiseLoadRequestEvent(sceneToLoad,firstPosition,true);}//加載場景前置工作private void OnLoadRequestEvent(GameSceneSO locationToGo, Vector3 posToGo, bool fadeScreen){if(isLoading)return;isLoading = true;sceneToLoad = locationToGo;this.posToGo = posToGo;this.fadeScreen = fadeScreen;if(currentloadScene != null)StartCoroutine(UnLoadPreviousScene());elseLoadNewScene();}//卸載之前場景private IEnumerator UnLoadPreviousScene(){unLoadedEvent.LoadRequestEvent(sceneToLoad, posToGo, fadeScreen);//等待當前場景完全卸載yield return currentloadScene.sceneReference.UnLoadScene();LoadNewScene();}//加載新的場景private void LoadNewScene(){//加載場景并且場景為激活狀態var loadingOption = sceneToLoad.sceneReference.LoadSceneAsync(LoadSceneMode.Additive);loadingOption.Completed += OnLoadComplete;}//加載完成之后執行任務private void OnLoadComplete(AsyncOperationHandle<SceneInstance> obj){currentloadScene = sceneToLoad;playerTrans.position = posToGo;isLoading = false;if(currentloadScene.sceneType != SceneType.Menu)afterSceneLoadedEvent.RaiseEvent();}
? ? ? ? 2.場景SO
[CreateAssetMenu(menuName = "Game Scene/GameSceneSO", fileName = "GameSceneSO")]
public class GameSceneSO : ScriptableObject
{public SceneType sceneType;public AssetReference sceneReference;
}
? ? ? ? 3.每個場景都需要勾選Addressable,添加進入Addressable Groups里面。
22.可交互邏輯
? ? ? ? 1.交互接口
public interface IInteractable
{void TriggerAction();
}
? ? ? ? 2.可交互邏輯
public class Chest : MonoBehaviour,IInteractable
{public void TriggerAction(){Debug.Log("Open Chest!");}
}
? ? ? ? 3.玩家交互邏輯?
public class Sign : MonoBehaviour
{private IInteractable targetItem;private bool canPress;private void OnTriggerStay2D(Collider2D other){if (other.CompareTag("Interactable")){targetItem = other.GetComponent<IInteractable>();canPress = true;}}private void OnTriggerExit2D(Collider2D other){canPress = false;}private void OnConfirm(InputAction.CallbackContext obj){if (canPress && targetItem != null){targetItem.TriggerAction();}}
}
注:獲取可交互物體對應的接口,然后執行接口函數,就會執行不同物體的不同方法。