From fd32018193d152f780f691538fa4ccde7364ed92 Mon Sep 17 00:00:00 2001 From: sheep <2502557798@qq.com> Date: Sat, 18 Jun 2022 13:57:28 +0800 Subject: [PATCH] Beta --- 00.Scripts/Characters/FootStepTrigger.cs | 65 ++++++++++++ 00.Scripts/Characters/FootStepTrigger.cs.meta | 11 ++ .../Characters/Player/CameraTestController.cs | 15 +-- 00.Scripts/Characters/Player/PlayerManager.cs | 15 +-- 00.Scripts/Characters/Player/PlayerMove.cs | 32 ++++-- 00.Scripts/Environment/Day_Follows_Night.cs | 47 +++++++++ .../Environment/Day_Follows_Night.cs.meta | 11 ++ 00.Scripts/ImpactEffect/IImpactEffect.cs | 4 +- 00.Scripts/Interact/InteractableObj.cs | 6 ++ 00.Scripts/Interact/NpcInteract.cs | 22 ++-- 00.Scripts/Manager/AudioManager.cs | 21 ++++ 00.Scripts/Manager/AudioManager.cs.meta | 11 ++ 00.Scripts/Manager/GameDataManager.cs | 18 ++++ 00.Scripts/Manager/LoadManager.cs | 10 +- 00.Scripts/Manager/NpcGenerateManager.cs | 9 +- 00.Scripts/Manager/QuestManager.cs | 9 +- 00.Scripts/ScriptableObject/Dialog_SO.cs | 5 +- .../ScriptableObject/PlayerSaveData_SO.cs | 3 + 00.Scripts/ScriptableObject/Quest_SO.cs | 36 +++++-- 00.Scripts/UI/DialogPanel.cs | 25 ++++- 00.Scripts/UI/LoadPanel.cs | 99 ++++++++++++++---- 00.Scripts/UI/MainMenu.cs | 6 +- 00.Scripts/UI/Panel.cs | 65 ++++++++++++ 00.Scripts/UI/Panel.cs.meta | 11 ++ 00.Scripts/UI/Phone/App_Modifier.cs | 45 ++++++++ 00.Scripts/UI/Phone/App_Modifier.cs.meta | 11 ++ 00.Scripts/UI/Phone/App_PlayerInfo.cs | 5 + 00.Scripts/UI/Phone/PhonePanel.cs | 2 + ...\346\237\245\346\212\245\345\221\212.docx" | Bin 0 -> 32163 bytes 29 files changed, 545 insertions(+), 74 deletions(-) create mode 100644 00.Scripts/Characters/FootStepTrigger.cs create mode 100644 00.Scripts/Characters/FootStepTrigger.cs.meta create mode 100644 00.Scripts/Environment/Day_Follows_Night.cs create mode 100644 00.Scripts/Environment/Day_Follows_Night.cs.meta create mode 100644 00.Scripts/Manager/AudioManager.cs create mode 100644 00.Scripts/Manager/AudioManager.cs.meta create mode 100644 00.Scripts/UI/Panel.cs create mode 100644 00.Scripts/UI/Panel.cs.meta create mode 100644 00.Scripts/UI/Phone/App_Modifier.cs create mode 100644 00.Scripts/UI/Phone/App_Modifier.cs.meta create mode 100644 "\343\200\212\347\246\217\345\244\247\346\250\241\346\213\237\345\231\250\343\200\213\342\200\224\342\200\224\347\224\250\346\210\267\350\260\203\346\237\245\346\212\245\345\221\212.docx" diff --git a/00.Scripts/Characters/FootStepTrigger.cs b/00.Scripts/Characters/FootStepTrigger.cs new file mode 100644 index 0000000..4deb7e3 --- /dev/null +++ b/00.Scripts/Characters/FootStepTrigger.cs @@ -0,0 +1,65 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class FootStepTrigger : MonoBehaviour +{ + //成员_触发器 + protected Collider _trigger; + public Collider Trigger + { + get + { + if (_trigger == null) _trigger = GetComponent(); + return _trigger; + } + } + + //成员_音源 + protected AudioSource _audioSource; + public AudioSource AudioSource + { + get + { + if (_audioSource == null) _audioSource = GetComponent(); + return _audioSource; + } + } + + //冷却时间 + protected float coolTime=.45f; + protected bool canUse = true; + + //debug绘制 + void OnDrawGizmos() + { + if (!Trigger) return; + Color color = Color.green; + color.a = 0.5f; + Gizmos.color = color; + if (Trigger is SphereCollider) + { + Gizmos.DrawSphere((Trigger.bounds.center), (Trigger as SphereCollider).radius); + } + } + + private void OnTriggerEnter(Collider other) + { + if (other.GetComponent()) return; + if (!canUse) return; + + var stepAudioList = AudioManager.GetInstance().FootStepAudios; + AudioClip audioTemp = stepAudioList[Random.Range(0, stepAudioList.Length)]; + + AudioSource.PlayOneShot(audioTemp); + + canUse = false; + StartCoroutine(SetCanUse()); + } + + IEnumerator SetCanUse() + { + yield return new WaitForSeconds(coolTime); + canUse = true; + } +} diff --git a/00.Scripts/Characters/FootStepTrigger.cs.meta b/00.Scripts/Characters/FootStepTrigger.cs.meta new file mode 100644 index 0000000..d0a51d7 --- /dev/null +++ b/00.Scripts/Characters/FootStepTrigger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 14342d96177d6de46b0bca90c7823d0d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/00.Scripts/Characters/Player/CameraTestController.cs b/00.Scripts/Characters/Player/CameraTestController.cs index 717d76a..c48743e 100644 --- a/00.Scripts/Characters/Player/CameraTestController.cs +++ b/00.Scripts/Characters/Player/CameraTestController.cs @@ -79,19 +79,19 @@ namespace FunTools Vector3 GetInputTranslationDirection() { Vector3 direction = new Vector3(); - if (Input.GetKey(KeyCode.W)) + if (Input.GetKey(KeyCode.UpArrow)) { direction += Vector3.forward; } - if (Input.GetKey(KeyCode.S)) + if (Input.GetKey(KeyCode.DownArrow)) { direction += Vector3.back; } - if (Input.GetKey(KeyCode.A)) + if (Input.GetKey(KeyCode.LeftArrow)) { direction += Vector3.left; } - if (Input.GetKey(KeyCode.D)) + if (Input.GetKey(KeyCode.RightArrow)) { direction += Vector3.right; } @@ -108,14 +108,15 @@ namespace FunTools void Update() { - // Exit Sample - if (Input.GetKey(KeyCode.Escape)) + // Exit Sample 傻逼,这边之前是直接退出游戏,复用别人代码之前还是得看看 + // 相机还是直接通过PlayerManager关闭吧,这边关闭逻辑有点混乱,输入都在PlayerInput当中处理 + /*if (Input.GetKey(KeyCode.Escape)) { Application.Quit(); #if UNITY_EDITOR UnityEditor.EditorApplication.isPlaying = false; #endif - } + }*/ // Hide and lock cursor when right mouse button pressed if (Input.GetMouseButtonDown(1)) diff --git a/00.Scripts/Characters/Player/PlayerManager.cs b/00.Scripts/Characters/Player/PlayerManager.cs index 2b8a9c0..675339d 100644 --- a/00.Scripts/Characters/Player/PlayerManager.cs +++ b/00.Scripts/Characters/Player/PlayerManager.cs @@ -52,9 +52,10 @@ public class PlayerManager : MonoBehaviour cameraSjw.SetActive(egleFlag); //将摄像机的状态设为启用或者不启用 } - // 如果开启鹰眼的话,就不处理玩家的其他输入,, 加一个如何开启了事件面板就不处理玩家输入 - if (!egleFlag) - { + // 如果开启鹰眼的话,就不处理玩家的其他输入,, 加一个如果开启了事件面板就不处理玩家输入 + //暂时注释掉了,可以同时操控相机和玩家 + //if (!egleFlag) + //{ playerInput.HandleInput(); if (cameraHandler != null) @@ -62,7 +63,7 @@ public class PlayerManager : MonoBehaviour cameraHandler.FollowTarget(delta); cameraHandler.HandleCameraRotation(delta, playerInput.mouseX, playerInput.mouseY); } - } + //} } private void FixedUpdate() @@ -71,8 +72,8 @@ public class PlayerManager : MonoBehaviour // 如果开启鹰眼的话,就不处理玩家的其他输入,, 加一个如何开启了事件面板就不处理玩家输入 && !UIManager.GetInstance().accidentPanel.isActiveAndEnabled - if (!egleFlag) - { + //if (!egleFlag) + //{ //操作刚体 playerMove.UpdateMoveDirection(Camera.main.transform); playerMove.HandleMovement(); @@ -81,6 +82,6 @@ public class PlayerManager : MonoBehaviour playerMove.ControlJumpBehaviour(); playerMove.AirControl(); playerMove.UpdateAnimatorParameters(); - } + //} } } diff --git a/00.Scripts/Characters/Player/PlayerMove.cs b/00.Scripts/Characters/Player/PlayerMove.cs index bc24892..1414f4d 100644 --- a/00.Scripts/Characters/Player/PlayerMove.cs +++ b/00.Scripts/Characters/Player/PlayerMove.cs @@ -86,6 +86,8 @@ public class PlayerMove : MonoBehaviour if (!isGround) return; //处于特殊动画时,不让动(交由动画控制) if (playerAnimation.GetBoolParameter("isInteracting")) return; + //不让动时,不让动(废话)(对话时不让动)(临时屎代码) + if (!CanControlMove()) return; //设置人物的速度(实际),动画混合数的速度(动画) SetControllerMoveSpeed(); @@ -99,11 +101,12 @@ public class PlayerMove : MonoBehaviour //设置预定的控制器速度(moveSpeed) protected virtual void SetControllerMoveSpeed() { + var targetSpringSpeed = GameDataManager.GetInstance().saveData.isFastRun ? sprintSpeed * 10 : sprintSpeed; if (GetMoveAmout() == 0) //TODO:无法顺滑停止。以后再说 { moveSpeed = Mathf.Lerp(moveSpeed, 0, 6 * Time.deltaTime);//6是平滑过渡值 } - else moveSpeed = Mathf.Lerp(moveSpeed, isSprinting ? sprintSpeed : normalSpeed, 6 * Time.deltaTime);//6是平滑过渡值 + else moveSpeed = Mathf.Lerp(moveSpeed, isSprinting ? targetSpringSpeed : normalSpeed, 6 * Time.deltaTime);//6是平滑过渡值 } @@ -188,7 +191,6 @@ public class PlayerMove : MonoBehaviour #endregion - #region 处理旋转 public void HandleRotation() { @@ -215,9 +217,15 @@ public class PlayerMove : MonoBehaviour /// public void TryDoJump() { - //TODO:感觉这里和处理移动那里挺像的。但又不像。 - if (!isGround) Debug.Log("可以禁止无限跳,但没必要"); + //不在地上时,检查无限跳 + if (!isGround) + { + if (!GameDataManager.GetInstance().saveData.isUnlimitJump) return; + } + if (playerAnimation.GetBoolParameter("isInteracting")) return; + //不让动时,不让动(废话)(对话时不让动)(临时屎代码) + if (!CanControlMove()) return; //跳! jumpCounter = jumpTimer; @@ -256,15 +264,18 @@ public class PlayerMove : MonoBehaviour /// public virtual void AirControl() { + //Debug.Log(isGround); //目前属实没啥内容很单薄。单薄到想移到别的地方去。不过还是先放着吧 if (isGround) return; + //TODO:重要bug,有时候不知道为啥检测的isground是错的,来不及了不管了,直接暴力if + //猜测是地面检测的射线还是什么东西检测到了紧贴的非地面的其他物体上导致误判,来不及了不管了 + if (!CanControlMove()) return; MoveUnit(moveDirection, true); } #endregion - #region 地面检测 public virtual void CheckGround() @@ -341,6 +352,15 @@ public class PlayerMove : MonoBehaviour #endregion - + //对话时,不让移动和跳跃,目前写的比较粗暴 + public bool CanControlMove() + { + if (UIManager.GetInstance().dialogPanel.gameObject.activeInHierarchy) + { + StopCharacterWithLerp(); + return false; + } + return true; + } } diff --git a/00.Scripts/Environment/Day_Follows_Night.cs b/00.Scripts/Environment/Day_Follows_Night.cs new file mode 100644 index 0000000..155834f --- /dev/null +++ b/00.Scripts/Environment/Day_Follows_Night.cs @@ -0,0 +1,47 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Day_Follows_Night : MonoBehaviour +{ + public Material[] mats; + private int index = 0; + + // Start is called before the first frame update + void Start() + { + //判断是否是夜晚,是则进行切换 默认加载白天 + if((int)GameDataManager.GetInstance().saveData.dayTimeEnum == 2) + { + Debug.Log(GameDataManager.GetInstance().saveData.dayTimeEnum); + ChangeBox(); + Change_Light(); + } + } + + /// + /// 改变天空盒 + /// + private void ChangeBox() + { + RenderSettings.skybox = mats[index]; + index++; + index %= mats.Length; + } + + /// + /// 根据场景的不同对灯光进行不同的处理 + /// + private void Change_Light() + { + if (LoadManager.LoadSceneName == null) return; + + if (LoadManager.LoadSceneName.Equals("05_PlayGroundScene")) + { + GameObject sun = GameObject.Find("Directional Light B"); + if (sun!=null) + sun.SetActive(false); + } + } + +} diff --git a/00.Scripts/Environment/Day_Follows_Night.cs.meta b/00.Scripts/Environment/Day_Follows_Night.cs.meta new file mode 100644 index 0000000..091d0b4 --- /dev/null +++ b/00.Scripts/Environment/Day_Follows_Night.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e6a564421404bf346a75a69b9e82623a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/00.Scripts/ImpactEffect/IImpactEffect.cs b/00.Scripts/ImpactEffect/IImpactEffect.cs index 1b93dc7..d791d28 100644 --- a/00.Scripts/ImpactEffect/IImpactEffect.cs +++ b/00.Scripts/ImpactEffect/IImpactEffect.cs @@ -60,7 +60,6 @@ public class IImpactEffect : MonoBehaviour case ImpactType.降低体力://暂定:以后是否新写一个消耗类或条件类。加上前置判断。 GameDataManager.GetInstance().saveData.currentAP -= impact.value; - UIManager.GetInstance().tipsInfoPanel.AddTipsInfo("你的体力消耗了" + impact.value + "点"); break; @@ -88,7 +87,7 @@ public class IImpactEffect : MonoBehaviour break; case ImpactType.完成任务: - EventManager.GetInstance().EventTrigger(impact.quest_SO.questNeed.NeedToString()); + EventManager.GetInstance().EventTrigger(impact.quest_SO.NeedToString()); break; case ImpactType.场景跳转到: @@ -100,6 +99,7 @@ public class IImpactEffect : MonoBehaviour UIManager.GetInstance().accidentPanel.SetAccident_SO(); break; + default: Debug.Log(impact.value); break; diff --git a/00.Scripts/Interact/InteractableObj.cs b/00.Scripts/Interact/InteractableObj.cs index 1e68368..115ad87 100644 --- a/00.Scripts/Interact/InteractableObj.cs +++ b/00.Scripts/Interact/InteractableObj.cs @@ -16,6 +16,9 @@ public class InteractableObj : MonoBehaviour , IInteraction protected void OnTriggerEnter(Collider other) { + //给屎山加点料 + if (other.GetComponent()) return; + //PlayerManager player=other.GetComponent(); PlayerManager player = other.GetComponentInParent();//现在是检测UnitBlockerCollider了 if (player != null)//检测到玩家进入交互范围 @@ -26,6 +29,9 @@ public class InteractableObj : MonoBehaviour , IInteraction protected void OnTriggerExit(Collider other) { + //给屎山加点料 + if (other.GetComponent()) return; + PlayerManager player = other.GetComponentInParent(); if (player != null)//检测到玩家离开交互范围 { diff --git a/00.Scripts/Interact/NpcInteract.cs b/00.Scripts/Interact/NpcInteract.cs index 3bd8e65..7df79f4 100644 --- a/00.Scripts/Interact/NpcInteract.cs +++ b/00.Scripts/Interact/NpcInteract.cs @@ -24,23 +24,32 @@ public class NpcInteract : InteractableObj public void Awake() { + if (npc_SO == null) + { + Destroy(gameObject); + return; + } + //读取SO。设置Npc实体的各项属性 dialog_SO = npc_SO.dialog_SO; //播放指定动画 anim = GetComponentInChildren(); - anim.CrossFade(npc_SO.PlayAnimName, .2f); + if (anim) + anim.CrossFade(npc_SO.PlayAnimName, .2f); if (pivotTrans!=null) { Text textUI = GetComponentInChildren(); - textUI.text = npc_SO.NpcName; + if (textUI!=null) + textUI.text = npc_SO.NpcName; } } private void OnEnable() { - anim.CrossFade(npc_SO.PlayAnimName,.2f); + if (anim) + anim.CrossFade(npc_SO.PlayAnimName,.2f); } protected void Update() @@ -58,10 +67,9 @@ public class NpcInteract : InteractableObj UIManager.GetInstance().dialogPanel.StartADialog(dialog_SO, 0); //事件中心:交互NPC - var need = new QuestNeed(); - need.questNeedType = QuestNeedType.交互; - need.stringValue = npc_SO.NpcName; - EventManager.GetInstance().EventTrigger(need.NeedToString()); + //TODO: 比较临时工的行为 + EventManager.GetInstance().EventTrigger("交互_"+npc_SO.NpcName); + } else { diff --git a/00.Scripts/Manager/AudioManager.cs b/00.Scripts/Manager/AudioManager.cs new file mode 100644 index 0000000..4c9f26b --- /dev/null +++ b/00.Scripts/Manager/AudioManager.cs @@ -0,0 +1,21 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class AudioManager : MonoSingleTon +{ + public AudioClip[] FootStepAudios; + public AudioClip bgm; + + protected AudioSource bgmAudioSource; + + private void Awake() + { + bgmAudioSource = GetComponent(); + + bgmAudioSource.clip = bgm; + bgmAudioSource.Play(); + } + + +} diff --git a/00.Scripts/Manager/AudioManager.cs.meta b/00.Scripts/Manager/AudioManager.cs.meta new file mode 100644 index 0000000..a14eecd --- /dev/null +++ b/00.Scripts/Manager/AudioManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c13b7e6532a778f42b90fde655fc109e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/00.Scripts/Manager/GameDataManager.cs b/00.Scripts/Manager/GameDataManager.cs index 95fd6de..3a8db68 100644 --- a/00.Scripts/Manager/GameDataManager.cs +++ b/00.Scripts/Manager/GameDataManager.cs @@ -6,9 +6,27 @@ public class GameDataManager : MonoSingleTon { //玩家存档数据。一般是开始游戏后会读取或新建一个默认的。手动拖拽赋值只用于测试。 public PlayerSaveData_SO saveData; + //新存档。开始游戏时用,不过实际上应该时可以选皮肤改名字选初始职业(卷王 土豪 一无所有者) + public PlayerSaveData_SO newSaveData; public void Awake() { QuestManager.GetInstance().Init(); } + + public void TempSetSaveDataToNew() + { + saveData.Strength = newSaveData.Strength; + saveData.Intelligence = newSaveData.Intelligence; + saveData.Communication = newSaveData.Communication; + + saveData.money = newSaveData.money; + saveData.mood = newSaveData.mood; + + saveData.GradeNum = 1; + saveData.dayTimeEnum = 0; + + saveData.currentQuest.Clear(); + saveData.finishedQuest.Clear(); + } } diff --git a/00.Scripts/Manager/LoadManager.cs b/00.Scripts/Manager/LoadManager.cs index e2983bb..e162d9e 100644 --- a/00.Scripts/Manager/LoadManager.cs +++ b/00.Scripts/Manager/LoadManager.cs @@ -5,7 +5,7 @@ using UnityEngine.SceneManagement; public class LoadManager : MonoSingleTon { - public string LoadSceneName; + public static string LoadSceneName; protected AsyncOperation operation; @@ -20,21 +20,20 @@ public class LoadManager : MonoSingleTon LoadSceneName = sceneName; UIManager.GetInstance().tryCloseCurrentUIObj(); StartCoroutine(LoadLevel()); - } IEnumerator LoadLevel() { - UIManager.GetInstance().loadPanel.gameObject.SetActive(true); + UIManager.GetInstance().loadPanel.RunEnable(); - yield return new WaitForSeconds(1); + yield return new WaitForSeconds(1); operation = SceneManager.LoadSceneAsync(LoadSceneName); while (!operation.isDone) { UIManager.GetInstance().loadPanel.loadProgressText.text = operation.progress.ToString(); - + UIManager.GetInstance().loadPanel.slider.value = operation.progress; if (operation.progress >= 0.9f) { @@ -50,4 +49,5 @@ public class LoadManager : MonoSingleTon } #endregion + } diff --git a/00.Scripts/Manager/NpcGenerateManager.cs b/00.Scripts/Manager/NpcGenerateManager.cs index e49906c..c77fb3d 100644 --- a/00.Scripts/Manager/NpcGenerateManager.cs +++ b/00.Scripts/Manager/NpcGenerateManager.cs @@ -5,7 +5,7 @@ using UnityEngine; //不用放进场景 public class NpcGenerateManager : MonoSingleTon { - private float generateRate = 0.4f;//每个npc随机生成的概率(也可以理解为可随机npc池子里,最终会刷出的npc的占比) + private float generateRate = 0.6f;//每个npc随机生成的概率(也可以理解为可随机npc池子里,最终会刷出的npc的占比) //包含场景内所有Npc [SerializeField]private List npcList = new List(); @@ -50,11 +50,12 @@ public class NpcGenerateManager : MonoSingleTon //筛选出满足条件的Npc foreach (var item in npcList) { + if (item.Npc_SO == null) continue; + item.gameObject.SetActive(false); - if (item.Npc_SO.requirement.getRequireBool()) - { + if (item.Npc_SO.requirement==null + || item.Npc_SO.requirement.getRequireBool()) npcCanGenList.Add(item); - } } //选取出将要生成的Npc diff --git a/00.Scripts/Manager/QuestManager.cs b/00.Scripts/Manager/QuestManager.cs index 9a7e221..f7fe1d7 100644 --- a/00.Scripts/Manager/QuestManager.cs +++ b/00.Scripts/Manager/QuestManager.cs @@ -11,6 +11,7 @@ public class QuestManager : MonoSingleTon //初始化进行中任务的监听 foreach (var item in GameDataManager.GetInstance().saveData.currentQuest) { + QuestRemoveListener(item); QuestAddListener(item); } } @@ -37,15 +38,15 @@ public class QuestManager : MonoSingleTon protected void QuestAddListener(Quest_SO quest_SO) { //增加监听。当听到达成某条件时,将对应任务"完成"。 - EventManager.GetInstance().AddEventListener(quest_SO.questNeed.NeedToString(), quest_SO.QuestFinish); - Debug.Log("添加事件监听:" + quest_SO.questNeed.NeedToString()); + EventManager.GetInstance().AddEventListener(quest_SO.NeedToString(), quest_SO.QuestFinish); + Debug.Log("添加事件监听:" + quest_SO.NeedToString()); } //为某任务移除监听 public void QuestRemoveListener(Quest_SO quest_SO) { - EventManager.GetInstance().RemoveEventListener(quest_SO.questNeed.NeedToString(), quest_SO.QuestFinish); - Debug.Log("移除事件监听:" + quest_SO.questNeed.NeedToString()); + EventManager.GetInstance().RemoveEventListener(quest_SO.NeedToString(), quest_SO.QuestFinish); + Debug.Log("移除事件监听:" + quest_SO.NeedToString()); } /// diff --git a/00.Scripts/ScriptableObject/Dialog_SO.cs b/00.Scripts/ScriptableObject/Dialog_SO.cs index 6be74f3..41bc6ce 100644 --- a/00.Scripts/ScriptableObject/Dialog_SO.cs +++ b/00.Scripts/ScriptableObject/Dialog_SO.cs @@ -47,6 +47,8 @@ public class SingleDialogSelection : IInteraction //重要! public void DoInteract(PlayerManager playerManager) { + //交给那边的方法去判断处理 + UIManager.GetInstance().dialogPanel.HandleNextDialog(nextDialogIndexes); //实现效果 foreach (var item in impacts) { @@ -61,8 +63,7 @@ public class SingleDialogSelection : IInteraction { UIManager.GetInstance().dialogPanel.EndDialog(); }*/ - //交给那边的方法去判断处理 - UIManager.GetInstance().dialogPanel.HandleNextDialog(nextDialogIndexes); + } diff --git a/00.Scripts/ScriptableObject/PlayerSaveData_SO.cs b/00.Scripts/ScriptableObject/PlayerSaveData_SO.cs index ed3ce3b..d5a77d4 100644 --- a/00.Scripts/ScriptableObject/PlayerSaveData_SO.cs +++ b/00.Scripts/ScriptableObject/PlayerSaveData_SO.cs @@ -31,6 +31,9 @@ public class PlayerSaveData_SO : ScriptableObject public List currentQuest;//进行中任务 public List finishedQuest;//已完成任务 + [Header("修改器设置")] + public bool isUnlimitJump = true;//是否能无限跳 + public bool isFastRun = false;//是否超级速度 } public enum DayTimeEnum { 早晨,中午,晚上}; diff --git a/00.Scripts/ScriptableObject/Quest_SO.cs b/00.Scripts/ScriptableObject/Quest_SO.cs index 29bfc52..8712bf7 100644 --- a/00.Scripts/ScriptableObject/Quest_SO.cs +++ b/00.Scripts/ScriptableObject/Quest_SO.cs @@ -13,7 +13,7 @@ public enum QuestFinishType { public enum QuestNeedType { - 交互 + 交互,只能ImpactEffect } [System.Serializable] @@ -28,10 +28,19 @@ public class QuestNeed [Tooltip("对应的int值(没有就不填)")] public int intValue = 1; - public string NeedToString() - { - return questNeedType + "_" + stringValue; - } + //public string NeedToString() + //{ + // switch (questNeedType) + // { + // case QuestNeedType.交互: + // return questNeedType + "_" + stringValue; + // case QuestNeedType.只能ImpactEffect: + // return questNeedType + "_" + ; + // break; + // default: + // break; + // } + //} } #endregion @@ -50,6 +59,8 @@ public class Quest_SO : ScriptableObject [TextArea] public string QuestNeedDescription;//任务达成条件描述(偏正式) [Tooltip("是否只能领取一次")] public bool onlyOnce = false; + [Tooltip("完成后直接移除")] + public bool deleteFinish = false; [Tooltip("达成条件")] public QuestNeed questNeed; @@ -58,6 +69,18 @@ public class Quest_SO : ScriptableObject public ImpactValue[] QuestReward;//任务报酬 + public string NeedToString() + { + switch (questNeed.questNeedType) + { + case QuestNeedType.交互: + return questNeed.questNeedType + "_" + questNeed.stringValue; + } + return questNeed + "_" + QuestName + "_" + name ; + } + + + //任务完成时的效果 public void QuestFinish() { @@ -66,7 +89,7 @@ public class Quest_SO : ScriptableObject QuestManager.GetInstance().QuestRemoveListener(this); //列表添加删除 GameDataManager.GetInstance().saveData.currentQuest.Remove(this); - GameDataManager.GetInstance().saveData.finishedQuest.Add(this); + if (!deleteFinish) GameDataManager.GetInstance().saveData.finishedQuest.Add(this); //提示 UIManager.GetInstance().tipsInfoPanel.AddTipsInfo("【"+QuestName+"】已完成!"); //实现效果 @@ -76,6 +99,7 @@ public class Quest_SO : ScriptableObject } } + //任务给予者 //完成条件 } diff --git a/00.Scripts/UI/DialogPanel.cs b/00.Scripts/UI/DialogPanel.cs index 8945aaf..fceaef8 100644 --- a/00.Scripts/UI/DialogPanel.cs +++ b/00.Scripts/UI/DialogPanel.cs @@ -7,6 +7,7 @@ public class DialogPanel : MonoBehaviour { protected Text dialogTextUI; protected Dialog_SO currentDialogSO; + string allText;// 给屎山代码加点料,因为需要鼠标点击的时候全部输出需要的变量 private void Awake() { @@ -68,6 +69,28 @@ public class DialogPanel : MonoBehaviour protected void SetDialogText(string text) { - dialogTextUI.text = text; + allText = text; + StopAllCoroutines(); + StartCoroutine(TypeText(text, 0.05f)); + } + + // 协程逐字打印文本的效果,用协程产生延时的效果 + IEnumerator TypeText(string str,float interval) + { + int i = 0; + while (i <= str.Length) + { + dialogTextUI.text = str.Substring(0, i++); + yield return new WaitForSeconds(interval); + } + } + + private void Update() + { + if (Input.GetMouseButtonDown(0)) + { + StopAllCoroutines(); + dialogTextUI.text = allText; + } } } diff --git a/00.Scripts/UI/LoadPanel.cs b/00.Scripts/UI/LoadPanel.cs index 6f68480..273c590 100644 --- a/00.Scripts/UI/LoadPanel.cs +++ b/00.Scripts/UI/LoadPanel.cs @@ -9,7 +9,10 @@ using UnityEngine.UI; public class LoadPanel : MonoBehaviour { //加载文字。目前对这玩意儿的改动都暂时在GameDataManager里。 - [HideInInspector] public Text loadProgressText; + public Text loadProgressText; + public Slider slider;//加载的进度条 + public Image sliderImage;// 进度条上的图片,为了实现进度条的滚动 + [Tooltip("显示的百分比")]public Text text;//显示的百分比 protected Image backGroundImg; public Sprite[] imgArrays; @@ -21,38 +24,92 @@ public class LoadPanel : MonoBehaviour backGroundImg = GetComponentInChildren(); } + //临时用,不管了 + public void RunEnable() + { + gameObject.SetActive(true); + //StartCoroutine(ChangeBackgroundImg());//持续切换背景图片 + ChangeBackgroundImg(); + StartCoroutine(RunSlider()); + } + private void OnEnable() { - StartCoroutine(ChangeBackgroundImg());//持续切换背景图片 + //全放到上面的RunEnable里了 + } + + private void OnDisable() + { + StopAllCoroutines(); } - - IEnumerator ChangeBackgroundImg() + // 两个update都试了一下,滚动的校徽看起来都挺卡的,聊胜于无吧 + /*private void FixedUpdate() { - while(gameObject.activeInHierarchy) + sliderImage.transform.localEulerAngles = new Vector3(0, 0, sliderImage.transform.rotation.z + 100f); + } + + private void Update() + { + sliderImage.transform.localEulerAngles = new Vector3(0, 0, sliderImage.transform.rotation.z + 100f); + }*/ + + /// + /// 协程实现进度条上的图片的滚动 + /// + IEnumerator RunSlider() + { + int i = 0; + while(i < 250) { - SetBackgroundImg(); - yield return new WaitForSeconds(4); + sliderImage.transform.localEulerAngles = new Vector3(0, 0, sliderImage.transform.rotation.z + 100f); + yield return new WaitForSeconds(0.04f); } + StopAllCoroutines(); + } + + + /// + /// 实现随机选择一张图片进行加载 + /// + private void ChangeBackgroundImg() + { + backGroundImg.sprite = imgArrays[Random.Range(0,imgArrays.Length)]; } + + //IEnumerator ChangeBackgroundImg() + //{ + // while(gameObject.activeInHierarchy) + // { + // SetBackgroundImg(); + // yield return new WaitForSeconds(4); + // } + //} + + + protected void SetBackgroundImg() { - Sprite nextImg = null; - if (backGroundImg == null) return; - if (imgArrays.Length == 1) - { - nextImg = imgArrays[0]; - } - else - { - while (nextImg != backGroundImg.sprite) - { - nextImg = imgArrays[Random.Range(0, imgArrays.Length)]; - } - } + //Sprite nextImg = null; + //if (backGroundImg == null) return; + //if (imgArrays.Length == 1) + //{ + // nextImg = imgArrays[0]; + //} + //else + //{ + // //TODO:沈建伟来写一下开始时随机选一张图 + //这边while代码最好不要了,会有死循环 + // //while (nextImg != backGroundImg.sprite) + // //{ + + // // // + // // //nextImg = imgArrays[Random.Range(0, imgArrays.Length)]; + // //} + //} - backGroundImg.sprite = nextImg; + //backGroundImg.sprite = nextImg; } } diff --git a/00.Scripts/UI/MainMenu.cs b/00.Scripts/UI/MainMenu.cs index 96b2205..aa4c778 100644 --- a/00.Scripts/UI/MainMenu.cs +++ b/00.Scripts/UI/MainMenu.cs @@ -47,9 +47,10 @@ public class MainMenu : MonoBehaviour /// void NewGame(PlayableDirector obj) { + //设置SO + GameDataManager.GetInstance().TempSetSaveDataToNew(); // 转换场景 LoadManager.GetInstance().LoadSceneByName("03_dormitory02"); - //LoadManager.GetInstance().LoadSceneByName("03_dormitory02"); Debug.Log("开始新游戏"); @@ -57,8 +58,9 @@ public class MainMenu : MonoBehaviour void ContinueGame() { - Debug.Log("读取存档"); //转换场景,读取进度 + LoadManager.GetInstance().LoadSceneByName("03_dormitory02"); + Debug.Log("读取存档"); } void SettingsGame() diff --git a/00.Scripts/UI/Panel.cs b/00.Scripts/UI/Panel.cs new file mode 100644 index 0000000..a8ce2a4 --- /dev/null +++ b/00.Scripts/UI/Panel.cs @@ -0,0 +1,65 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +public class Panel : MonoBehaviour +{ + public Image panelImage; + public AnimationCurve showCurve; + public AnimationCurve hideCurve; + public float animationSpeed = 2; + public float transparency = 0.5f; + + // 使用协程来进行面板的渐入渐出效果 + IEnumerator ShowPanel() + { + float timer = 0; + while (panelImage.color.a < 1) + { + panelImage.color = new Vector4(1, 1, 1, showCurve.Evaluate(timer)); + timer += Time.deltaTime * animationSpeed; + yield return null; + } + } + + IEnumerator HidePanel() + { + float timer = 0; + while (panelImage.color.a > 0) + { + panelImage.color = new Vector4(1, 1, 1, hideCurve.Evaluate(timer)); + timer += Time.deltaTime * animationSpeed; + yield return null; + } + } + + // 打开面板,渐入效果 + public void OpenPanel() + { + StopAllCoroutines(); + StartCoroutine(ShowPanel()); + } + + // 关闭面板,渐出效果 + public void ClosePanel() + { + StopAllCoroutines(); + StartCoroutine(HidePanel()); + } + + // 这是测试,要删掉,左键打开,右键关闭 + public void Update() + { + if (Input.GetMouseButtonDown(0)) + { + StopAllCoroutines(); + StartCoroutine(ShowPanel()); + } + if (Input.GetMouseButtonDown(1)) + { + StopAllCoroutines(); + StartCoroutine(HidePanel()); + } + } +} diff --git a/00.Scripts/UI/Panel.cs.meta b/00.Scripts/UI/Panel.cs.meta new file mode 100644 index 0000000..53452ef --- /dev/null +++ b/00.Scripts/UI/Panel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f28d31d667701cd4ba784ce6cf9a312a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/00.Scripts/UI/Phone/App_Modifier.cs b/00.Scripts/UI/Phone/App_Modifier.cs new file mode 100644 index 0000000..4e3d762 --- /dev/null +++ b/00.Scripts/UI/Phone/App_Modifier.cs @@ -0,0 +1,45 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +public class App_Modifier : MonoBehaviour +{ + public Text playerInfoText;//目前暂时使用手动拖拽赋值 + + //激活时自动调用 + private void OnEnable() + { + SetInfoText(); + } + + public void SwitchUnlimitJump() + { + var saveData = GameDataManager.GetInstance().saveData; + saveData.isUnlimitJump = !saveData.isUnlimitJump; + SetInfoText(); + } + public void SwitchFastRun() + { + var saveData = GameDataManager.GetInstance().saveData; + saveData.isFastRun = !saveData.isFastRun; + SetInfoText(); + } + + protected void SetInfoText() + { + //读取目前玩家游戏数据 + var saveData = GameDataManager.GetInstance().saveData; + string s = ""; + + //设置字符串 + s += "无限跳:" + BoolToRichText(saveData.isUnlimitJump) + "\n"; + s += "兔符咒:" + BoolToRichText(saveData.isFastRun) + "\n"; + + playerInfoText.text = s; + } + protected string BoolToRichText(bool value) + { + return value ? " 启用 " : " 关闭 "; + } +} diff --git a/00.Scripts/UI/Phone/App_Modifier.cs.meta b/00.Scripts/UI/Phone/App_Modifier.cs.meta new file mode 100644 index 0000000..6377f7d --- /dev/null +++ b/00.Scripts/UI/Phone/App_Modifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 84ffaa8a55751fc41bcf13e08c439c03 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/00.Scripts/UI/Phone/App_PlayerInfo.cs b/00.Scripts/UI/Phone/App_PlayerInfo.cs index d4171c6..e7c1119 100644 --- a/00.Scripts/UI/Phone/App_PlayerInfo.cs +++ b/00.Scripts/UI/Phone/App_PlayerInfo.cs @@ -24,6 +24,11 @@ public class App_PlayerInfo : MonoBehaviour s += "气力:" + saveData.Strength + "\n"; s += "学识:" + saveData.Intelligence + "\n"; s += "社交:" + saveData.Communication + "\n"; + s += "\n"; + s += "金钱: " + saveData.money + "\n"; + s += "心情: " + saveData.money + "\n"; + s += "年级: " + saveData.GradeNum + "\n"; + s += "时间段: " + saveData.dayTimeEnum.ToString() + "\n"; playerInfoText.text = s; } diff --git a/00.Scripts/UI/Phone/PhonePanel.cs b/00.Scripts/UI/Phone/PhonePanel.cs index fadeea1..f61ec25 100644 --- a/00.Scripts/UI/Phone/PhonePanel.cs +++ b/00.Scripts/UI/Phone/PhonePanel.cs @@ -37,6 +37,8 @@ public class PhonePanel : MonoBehaviour /// public void PointApp(int add) { + if (gameObject.activeSelf == false) return; + currentAppIndex += add; currentAppIndex = (currentAppIndex + appList.Count) % appList.Count;//循环 diff --git "a/\343\200\212\347\246\217\345\244\247\346\250\241\346\213\237\345\231\250\343\200\213\342\200\224\342\200\224\347\224\250\346\210\267\350\260\203\346\237\245\346\212\245\345\221\212.docx" "b/\343\200\212\347\246\217\345\244\247\346\250\241\346\213\237\345\231\250\343\200\213\342\200\224\342\200\224\347\224\250\346\210\267\350\260\203\346\237\245\346\212\245\345\221\212.docx" new file mode 100644 index 0000000000000000000000000000000000000000..900b29e2aed9cb04285f353a658842ee8c187e94 GIT binary patch literal 32163 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 E1DkYu