【m】框架大更新

This commit is contained in:
2025-10-31 11:18:23 +08:00
parent ae6e7c804b
commit 8e1d52ddbf
1883 changed files with 213934 additions and 640 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 358519dfd46c3c84d9300408c743ebf7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,234 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Event;
using UniFramework.Utility;
using YooAsset;
using Random = UnityEngine.Random;
[Serializable]
public class RoomBoundary
{
public float xMin, xMax, zMin, zMax;
}
/// <summary>
/// 战斗房间
/// </summary>
public class BattleRoom
{
private enum ESteps
{
None,
Ready,
SpawnEnemy,
WaitSpawn,
WaitWave,
GameOver,
}
private readonly EventGroup _eventGroup = new EventGroup();
private GameObject _roomRoot;
// 关卡参数
private const int EnemyCount = 10;
private const int EnemyScore = 10;
private const int AsteroidScore = 1;
private readonly Vector3 _spawnValues = new Vector3(6, 0, 20);
private readonly string[] _entityLocations = new string[]
{
"asteroid01", "asteroid02", "asteroid03", "enemy_ship"
};
private ESteps _steps = ESteps.None;
private int _totalScore = 0;
private int _waveSpawnCount = 0;
private readonly UniTimer _startWaitTimer = UniTimer.CreateOnceTimer(1f);
private readonly UniTimer _spawnWaitTimer = UniTimer.CreateOnceTimer(0.75f);
private readonly UniTimer _waveWaitTimer = UniTimer.CreateOnceTimer(4f);
private readonly List<AssetHandle> _handles = new List<AssetHandle>(1000);
/// <summary>
/// 初始化房间
/// </summary>
public void IntRoom()
{
// 创建房间根对象
_roomRoot = new GameObject("BattleRoom");
// 监听游戏事件
_eventGroup.AddListener<BattleEventDefine.PlayerDead>(OnHandleEventMessage);
_eventGroup.AddListener<BattleEventDefine.EnemyDead>(OnHandleEventMessage);
_eventGroup.AddListener<BattleEventDefine.AsteroidExplosion>(OnHandleEventMessage);
_eventGroup.AddListener<BattleEventDefine.PlayerFireBullet>(OnHandleEventMessage);
_eventGroup.AddListener<BattleEventDefine.EnemyFireBullet>(OnHandleEventMessage);
_steps = ESteps.Ready;
}
/// <summary>
/// 销毁房间
/// </summary>
public void DestroyRoom()
{
if (_eventGroup != null)
_eventGroup.RemoveAllListener();
if (_roomRoot != null)
GameObject.Destroy(_roomRoot);
foreach(var handle in _handles)
{
handle.Release();
}
_handles.Clear();
}
/// <summary>
/// 更新房间
/// </summary>
public void UpdateRoom()
{
if (_steps == ESteps.None || _steps == ESteps.GameOver)
return;
if (_steps == ESteps.Ready)
{
if (_startWaitTimer.Update(Time.deltaTime))
{
// 生成实体
var assetHandle = YooAssets.LoadAssetAsync<GameObject>("player_ship");
assetHandle.Completed += (AssetHandle handle) =>
{
handle.InstantiateSync(_roomRoot.transform);
};
_handles.Add(assetHandle);
_steps = ESteps.SpawnEnemy;
}
}
if (_steps == ESteps.SpawnEnemy)
{
var enemyLocation = _entityLocations[Random.Range(0, 4)];
Vector3 spawnPosition = new Vector3(Random.Range(-_spawnValues.x, _spawnValues.x), _spawnValues.y, _spawnValues.z);
Quaternion spawnRotation = Quaternion.identity;
// 生成实体
var assetHandle = YooAssets.LoadAssetAsync<GameObject>(enemyLocation);
assetHandle.Completed += (AssetHandle handle) =>
{
handle.InstantiateSync(spawnPosition, spawnRotation, _roomRoot.transform);
};
_handles.Add(assetHandle);
_waveSpawnCount++;
if (_waveSpawnCount >= EnemyCount)
{
_steps = ESteps.WaitWave;
}
else
{
_steps = ESteps.WaitSpawn;
}
}
if (_steps == ESteps.WaitSpawn)
{
if (_spawnWaitTimer.Update(Time.deltaTime))
{
_spawnWaitTimer.Reset();
_steps = ESteps.SpawnEnemy;
}
}
if (_steps == ESteps.WaitWave)
{
if (_waveWaitTimer.Update(Time.deltaTime))
{
_waveWaitTimer.Reset();
_waveSpawnCount = 0;
_steps = ESteps.SpawnEnemy;
}
}
}
/// <summary>
/// 接收事件
/// </summary>
/// <param name="message"></param>
private void OnHandleEventMessage(IEventMessage message)
{
if (message is BattleEventDefine.PlayerDead)
{
var msg = message as BattleEventDefine.PlayerDead;
// 创建爆炸效果
var assetHandle = YooAssets.LoadAssetAsync<GameObject>("explosion_player");
assetHandle.Completed += (AssetHandle handle) =>
{
handle.InstantiateSync(msg.Position, msg.Rotation, _roomRoot.transform);
};
_handles.Add(assetHandle);
_steps = ESteps.GameOver;
BattleEventDefine.GameOver.SendEventMessage();
}
else if (message is BattleEventDefine.EnemyDead)
{
var msg = message as BattleEventDefine.EnemyDead;
// 创建爆炸效果
var assetHandle = YooAssets.LoadAssetAsync<GameObject>("explosion_enemy");
assetHandle.Completed += (AssetHandle handle) =>
{
handle.InstantiateSync(msg.Position, msg.Rotation, _roomRoot.transform);
};
_handles.Add(assetHandle);
_totalScore += EnemyScore;
BattleEventDefine.ScoreChange.SendEventMessage(_totalScore);
}
else if (message is BattleEventDefine.AsteroidExplosion)
{
var msg = message as BattleEventDefine.AsteroidExplosion;
// 创建爆炸效果
var assetHandle = YooAssets.LoadAssetAsync<GameObject>("explosion_asteroid");
assetHandle.Completed += (AssetHandle handle) =>
{
handle.InstantiateSync(msg.Position, msg.Rotation, _roomRoot.transform);
};
_handles.Add(assetHandle);
_totalScore += AsteroidScore;
BattleEventDefine.ScoreChange.SendEventMessage(_totalScore);
}
else if (message is BattleEventDefine.PlayerFireBullet)
{
var msg = message as BattleEventDefine.PlayerFireBullet;
// 创建子弹实体
var assetHandle = YooAssets.LoadAssetAsync<GameObject>("player_bullet");
assetHandle.Completed += (AssetHandle handle) =>
{
handle.InstantiateSync(msg.Position, msg.Rotation, _roomRoot.transform);
};
_handles.Add(assetHandle);
}
else if (message is BattleEventDefine.EnemyFireBullet)
{
var msg = message as BattleEventDefine.EnemyFireBullet;
// 创建子弹实体
var assetHandle = YooAssets.LoadAssetAsync<GameObject>("enemy_bullet");
assetHandle.Completed += (AssetHandle handle) =>
{
handle.InstantiateSync(msg.Position, msg.Rotation, _roomRoot.transform);
};
_handles.Add(assetHandle);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d4dfc5f1cace4e8469e496d83b254ac7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EntityAsteroid : MonoBehaviour
{
public float MoveSpeed = -5f;
public float Tumble = 5f;
private Rigidbody _rigidbody;
void Awake()
{
_rigidbody = this.transform.GetComponent<Rigidbody>();
_rigidbody.velocity = this.transform.forward * MoveSpeed;
_rigidbody.angularVelocity = Random.insideUnitSphere * Tumble;
}
void OnTriggerEnter(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("player"))
{
BattleEventDefine.AsteroidExplosion.SendEventMessage(this.transform.position, this.transform.rotation);
GameObject.Destroy(this.gameObject);
}
}
void OnTriggerExit(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("Boundary"))
{
GameObject.Destroy(this.gameObject);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ffef5a382eef32d46b1d6175c85f644e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EntityBullet : MonoBehaviour
{
public float MoveSpeed = 20f;
public float DelayDestroyTime = 5f;
private Rigidbody _rigidbody;
void Awake()
{
_rigidbody = this.transform.GetComponent<Rigidbody>();
_rigidbody.velocity = this.transform.forward * MoveSpeed;
}
void OnTriggerEnter(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("Boundary"))
return;
var goName = this.gameObject.name;
if (goName.StartsWith("enemy_bullet"))
{
if (name.StartsWith("enemy") == false)
{
GameObject.Destroy(this.gameObject);
}
}
if (goName.StartsWith("player_bullet"))
{
if (name.StartsWith("player") == false)
{
GameObject.Destroy(this.gameObject);
}
}
}
void OnTriggerExit(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("Boundary"))
{
GameObject.Destroy(this.gameObject);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1a9d4ddd3c4e60245b6bc4f9f1435291
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EntityEffect : MonoBehaviour
{
public float DelayDestroyTime = 1f;
private void Awake()
{
Invoke(nameof(DelayDestroy), DelayDestroyTime);
}
private void DelayDestroy()
{
GameObject.Destroy(this.gameObject);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 014c1f9b87e247446bd7d558f8bf143e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,92 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class EntityEnemy : MonoBehaviour
{
private const float Dodge = 5f;
private const float Smoothing = 7.5f;
public RoomBoundary Boundary;
public float MoveSpeed = 20f;
public float FireInterval = 2f;
public Vector2 StartWait = new Vector2(0.5f, 1f);
public Vector2 ManeuverTime = new Vector2(1, 2);
public Vector2 ManeuverWait = new Vector2(1, 2);
private Transform _shotSpawn;
private Rigidbody _rigidbody;
private AudioSource _audioSource;
private float _lastFireTime = 0f;
private float _currentSpeed;
private float _targetManeuver;
void Awake()
{
_rigidbody = this.gameObject.GetComponent<Rigidbody>();
_audioSource = this.gameObject.GetComponent<AudioSource>();
_shotSpawn = this.transform.Find("shot_spawn");
_rigidbody.velocity = this.transform.forward * -5f;
_lastFireTime = Time.time;
_currentSpeed = _rigidbody.velocity.z;
_targetManeuver = 0f;
StartCoroutine(Evade());
}
void Update()
{
if (Time.time - _lastFireTime >= FireInterval)
{
_lastFireTime = Time.time;
_audioSource.Play();
BattleEventDefine.EnemyFireBullet.SendEventMessage(_shotSpawn.position, _shotSpawn.rotation);
}
}
void FixedUpdate()
{
float newManeuver = Mathf.MoveTowards(_rigidbody.velocity.x, _targetManeuver, Smoothing * Time.deltaTime);
_rigidbody.velocity = new Vector3(newManeuver, 0.0f, _currentSpeed);
_rigidbody.position = new Vector3
(
Mathf.Clamp(_rigidbody.position.x, Boundary.xMin, Boundary.xMax),
0.0f,
Mathf.Clamp(_rigidbody.position.z, Boundary.zMin, Boundary.zMax)
);
float tilt = 10f;
_rigidbody.rotation = Quaternion.Euler(0, 0, _rigidbody.velocity.x * -tilt);
}
void OnTriggerEnter(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("player"))
{
BattleEventDefine.EnemyDead.SendEventMessage(this.transform.position, this.transform.rotation);
GameObject.Destroy(this.gameObject);
}
}
void OnTriggerExit(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("Boundary"))
{
GameObject.Destroy(this.gameObject);
}
}
IEnumerator Evade()
{
yield return new WaitForSeconds(Random.Range(StartWait.x, StartWait.y));
while (true)
{
_targetManeuver = Random.Range(1, Dodge) * -Mathf.Sign(transform.position.x);
yield return new WaitForSeconds(Random.Range(ManeuverTime.x, ManeuverTime.y));
_targetManeuver = 0;
yield return new WaitForSeconds(Random.Range(ManeuverWait.x, ManeuverWait.y));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a613426c4968b3149b8bf9bf88fe41c7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EntityPlayer : MonoBehaviour
{
public RoomBoundary Boundary;
public float MoveSpeed = 10f;
public float FireRate = 0.25f;
private float _nextFireTime = 0f;
private Transform _shotSpawn;
private Rigidbody _rigidbody;
private AudioSource _audioSource;
void Awake()
{
_rigidbody = this.gameObject.GetComponent<Rigidbody>();
_audioSource = this.gameObject.GetComponent<AudioSource>();
_shotSpawn = this.transform.Find("shot_spawn");
}
void Update()
{
if (Input.GetButton("Fire1") && Time.time > _nextFireTime)
{
_nextFireTime = Time.time + FireRate;
_audioSource.Play();
BattleEventDefine.PlayerFireBullet.SendEventMessage(_shotSpawn.position, _shotSpawn.rotation);
}
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
_rigidbody.velocity = movement * MoveSpeed;
_rigidbody.position = new Vector3
(
Mathf.Clamp(GetComponent<Rigidbody>().position.x, Boundary.xMin, Boundary.xMax),
0.0f,
Mathf.Clamp(GetComponent<Rigidbody>().position.z, Boundary.zMin, Boundary.zMax)
);
float tilt = 5f;
_rigidbody.rotation = Quaternion.Euler(0.0f, 0.0f, _rigidbody.velocity.x * -tilt);
}
void OnTriggerEnter(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("enemy") || name.StartsWith("asteroid"))
{
BattleEventDefine.PlayerDead.SendEventMessage(this.transform.position, this.transform.rotation);
GameObject.Destroy(this.gameObject);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d3933af4e188ec44683e3c52784eadb0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e2f6bcc746b3d984e81caafa7d25467b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
using System;
using UnityEngine;
public class BackgroundScroller : MonoBehaviour
{
public float ScrollSpeed;
public float TileSizeZ;
private Vector3 _startPosition;
void Start()
{
_startPosition = transform.position;
}
void Update()
{
float newPosition = Mathf.Repeat(Time.time * ScrollSpeed, TileSizeZ);
this.transform.position = _startPosition + Vector3.forward * newPosition;
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 814f6a7e3ec8a40aaa3a2057e2695924
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Event;
using YooAsset;
public class Boot : MonoBehaviour
{
/// <summary>
/// 资源系统运行模式
/// </summary>
public EPlayMode PlayMode = EPlayMode.EditorSimulateMode;
void Awake()
{
Debug.Log($"资源系统运行模式:{PlayMode}");
Application.targetFrameRate = 60;
Application.runInBackground = true;
DontDestroyOnLoad(this.gameObject);
}
IEnumerator Start()
{
// 游戏管理器
GameManager.Instance.Behaviour = this;
// 初始化事件系统
UniEvent.Initalize();
// 初始化资源系统
YooAssets.Initialize();
// 加载更新页面
var go = Resources.Load<GameObject>("PatchWindow");
GameObject.Instantiate(go);
// 开始补丁更新流程
var operation = new PatchOperation("DefaultPackage", PlayMode);
YooAssets.StartOperation(operation);
yield return operation;
// 设置默认的资源包
var gamePackage = YooAssets.GetPackage("DefaultPackage");
YooAssets.SetDefaultPackage(gamePackage);
// 切换到主页面场景
SceneEventDefine.ChangeToHomeScene.SendEventMessage();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 41fef9a778e4e254b939e9dc3e553bf0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8428e7a0bb96bf946aa3034281990090
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,119 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Event;
public class BattleEventDefine
{
/// <summary>
/// 分数改变
/// </summary>
public class ScoreChange : IEventMessage
{
public int CurrentScores;
public static void SendEventMessage(int currentScores)
{
var msg = new ScoreChange();
msg.CurrentScores = currentScores;
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 游戏结束
/// </summary>
public class GameOver : IEventMessage
{
public static void SendEventMessage()
{
var msg = new GameOver();
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 敌人死亡
/// </summary>
public class EnemyDead : IEventMessage
{
public Vector3 Position;
public Quaternion Rotation;
public static void SendEventMessage(Vector3 position, Quaternion rotation)
{
var msg = new EnemyDead();
msg.Position = position;
msg.Rotation = rotation;
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 玩家死亡
/// </summary>
public class PlayerDead : IEventMessage
{
public Vector3 Position;
public Quaternion Rotation;
public static void SendEventMessage(Vector3 position, Quaternion rotation)
{
var msg = new PlayerDead();
msg.Position = position;
msg.Rotation = rotation;
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 小行星爆炸
/// </summary>
public class AsteroidExplosion : IEventMessage
{
public Vector3 Position;
public Quaternion Rotation;
public static void SendEventMessage(Vector3 position, Quaternion rotation)
{
var msg = new AsteroidExplosion();
msg.Position = position;
msg.Rotation = rotation;
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 敌人发射子弹
/// </summary>
public class EnemyFireBullet : IEventMessage
{
public Vector3 Position;
public Quaternion Rotation;
public static void SendEventMessage(Vector3 position, Quaternion rotation)
{
var msg = new EnemyFireBullet();
msg.Position = position;
msg.Rotation = rotation;
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 玩家发射子弹
/// </summary>
public class PlayerFireBullet : IEventMessage
{
public Vector3 Position;
public Quaternion Rotation;
public static void SendEventMessage(Vector3 position, Quaternion rotation)
{
var msg = new PlayerFireBullet();
msg.Position = position;
msg.Rotation = rotation;
UniEvent.SendMessage(msg);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 523858f19dde4204aad79345f342b0ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,111 @@
using UniFramework.Event;
using YooAsset;
public class PatchEventDefine
{
/// <summary>
/// 补丁包初始化失败
/// </summary>
public class InitializeFailed : IEventMessage
{
public static void SendEventMessage()
{
var msg = new InitializeFailed();
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 补丁流程步骤改变
/// </summary>
public class PatchStepsChange : IEventMessage
{
public string Tips;
public static void SendEventMessage(string tips)
{
var msg = new PatchStepsChange();
msg.Tips = tips;
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 发现更新文件
/// </summary>
public class FoundUpdateFiles : IEventMessage
{
public int TotalCount;
public long TotalSizeBytes;
public static void SendEventMessage(int totalCount, long totalSizeBytes)
{
var msg = new FoundUpdateFiles();
msg.TotalCount = totalCount;
msg.TotalSizeBytes = totalSizeBytes;
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 下载进度更新
/// </summary>
public class DownloadUpdate : IEventMessage
{
public int TotalDownloadCount;
public int CurrentDownloadCount;
public long TotalDownloadSizeBytes;
public long CurrentDownloadSizeBytes;
public static void SendEventMessage(DownloadUpdateData updateData)
{
var msg = new DownloadUpdate();
msg.TotalDownloadCount = updateData.TotalDownloadCount;
msg.CurrentDownloadCount = updateData.CurrentDownloadCount;
msg.TotalDownloadSizeBytes = updateData.TotalDownloadBytes;
msg.CurrentDownloadSizeBytes = updateData.CurrentDownloadBytes;
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 资源版本请求失败
/// </summary>
public class PackageVersionRequestFailed : IEventMessage
{
public static void SendEventMessage()
{
var msg = new PackageVersionRequestFailed();
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 资源清单更新失败
/// </summary>
public class PackageManifestUpdateFailed : IEventMessage
{
public static void SendEventMessage()
{
var msg = new PackageManifestUpdateFailed();
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 网络文件下载失败
/// </summary>
public class WebFileDownloadFailed : IEventMessage
{
public string FileName;
public string Error;
public static void SendEventMessage(DownloadErrorData errorData)
{
var msg = new WebFileDownloadFailed();
msg.FileName = errorData.FileName;
msg.Error = errorData.ErrorInfo;
UniEvent.SendMessage(msg);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7bb954fb42c50874b8897756e8b5dae5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
using UniFramework.Event;
public class SceneEventDefine
{
public class ChangeToHomeScene : IEventMessage
{
public static void SendEventMessage()
{
var msg = new ChangeToHomeScene();
UniEvent.SendMessage(msg);
}
}
public class ChangeToBattleScene : IEventMessage
{
public static void SendEventMessage()
{
var msg = new ChangeToBattleScene();
UniEvent.SendMessage(msg);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c56a83939686d3a4aa76b7d4ec704889
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using UniFramework.Event;
public class UserEventDefine
{
/// <summary>
/// 用户尝试再次初始化资源包
/// </summary>
public class UserTryInitialize : IEventMessage
{
public static void SendEventMessage()
{
var msg = new UserTryInitialize();
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 用户开始下载网络文件
/// </summary>
public class UserBeginDownloadWebFiles : IEventMessage
{
public static void SendEventMessage()
{
var msg = new UserBeginDownloadWebFiles();
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 用户尝试再次请求资源版本
/// </summary>
public class UserTryRequestPackageVersion : IEventMessage
{
public static void SendEventMessage()
{
var msg = new UserTryRequestPackageVersion();
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 用户尝试再次更新补丁清单
/// </summary>
public class UserTryUpdatePackageManifest : IEventMessage
{
public static void SendEventMessage()
{
var msg = new UserTryUpdatePackageManifest();
UniEvent.SendMessage(msg);
}
}
/// <summary>
/// 用户尝试再次下载网络文件
/// </summary>
public class UserTryDownloadWebFiles : IEventMessage
{
public static void SendEventMessage()
{
var msg = new UserTryDownloadWebFiles();
UniEvent.SendMessage(msg);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1bfe7ffc460fb234da96624844ab7e51
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cae7dcd2cee351e4390eebef0851486e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Event;
using YooAsset;
public class GameManager
{
private static GameManager _instance;
public static GameManager Instance
{
get
{
if (_instance == null)
_instance = new GameManager();
return _instance;
}
}
private readonly EventGroup _eventGroup = new EventGroup();
/// <summary>
/// 协程启动器
/// </summary>
public MonoBehaviour Behaviour;
private GameManager()
{
// 注册监听事件
_eventGroup.AddListener<SceneEventDefine.ChangeToHomeScene>(OnHandleEventMessage);
_eventGroup.AddListener<SceneEventDefine.ChangeToBattleScene>(OnHandleEventMessage);
}
/// <summary>
/// 开启一个协程
/// </summary>
public void StartCoroutine(IEnumerator enumerator)
{
Behaviour.StartCoroutine(enumerator);
}
/// <summary>
/// 接收事件
/// </summary>
private void OnHandleEventMessage(IEventMessage message)
{
if (message is SceneEventDefine.ChangeToHomeScene)
{
YooAssets.LoadSceneAsync("scene_home");
}
else if (message is SceneEventDefine.ChangeToBattleScene)
{
YooAssets.LoadSceneAsync("scene_battle");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f6630e7de79efb24b9263519ba4282e1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,75 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
internal class SceneBattle : MonoBehaviour
{
public GameObject CanvasDesktop;
private AssetHandle _windowHandle;
private AssetHandle _musicHandle;
private BattleRoom _battleRoom;
private IEnumerator Start()
{
// 加载战斗页面
_windowHandle = YooAssets.LoadAssetAsync<GameObject>("UIBattle");
yield return _windowHandle;
_windowHandle.InstantiateSync(CanvasDesktop.transform);
// 加载背景音乐
_musicHandle = YooAssets.LoadAssetAsync<AudioClip>("music_background");
yield return _musicHandle;
// 播放背景音乐
var audioSource = this.gameObject.AddComponent<AudioSource>();
audioSource.loop = true;
audioSource.clip = _musicHandle.AssetObject as AudioClip;
audioSource.Play();
// 切换场景的时候释放资源
var package = YooAssets.GetPackage("DefaultPackage");
var operation = package.UnloadUnusedAssetsAsync();
yield return operation;
_battleRoom = new BattleRoom();
_battleRoom.IntRoom();
}
private void OnDestroy()
{
// 释放资源句柄
if (_windowHandle != null)
{
_windowHandle.Release();
_windowHandle = null;
}
// 释放资源句柄
if (_musicHandle != null)
{
_musicHandle.Release();
_musicHandle = null;
}
// 释放资源句柄
if (_battleRoom != null)
{
_battleRoom.DestroyRoom();
_battleRoom = null;
}
// 切换场景的时候释放资源
if (YooAssets.Initialized)
{
var package = YooAssets.GetPackage("DefaultPackage");
var operation = package.UnloadUnusedAssetsAsync();
operation.WaitForAsyncComplete();
}
}
private void Update()
{
if (_battleRoom != null)
_battleRoom.UpdateRoom();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 54061fd8bcab2344e87b0faf0464c179
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
public class SceneHome : MonoBehaviour
{
public GameObject CanvasDesktop;
private AssetHandle _windowHandle;
private IEnumerator Start()
{
// 加载主页面
_windowHandle = YooAssets.LoadAssetAsync<GameObject>("UIHome");
yield return _windowHandle;
_windowHandle.InstantiateSync(CanvasDesktop.transform);
// 切换场景的时候释放资源
var package = YooAssets.GetPackage("DefaultPackage");
var operation = package.UnloadUnusedAssetsAsync();
yield return operation;
}
private void OnDestroy()
{
// 释放资源句柄
if (_windowHandle != null)
{
_windowHandle.Release();
_windowHandle = null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 41730f8e5f2b6e64abc4a03035c61ea5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0806ae86bd95bad4ca04d04b9084170f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 22a43ec58b9da1743bfa629be08ef1ac
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
internal class FsmClearCacheBundle : IStateNode
{
private StateMachine _machine;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
PatchEventDefine.PatchStepsChange.SendEventMessage("清理未使用的缓存文件!");
var packageName = (string)_machine.GetBlackboardValue("PackageName");
var package = YooAssets.GetPackage(packageName);
var operation = package.ClearCacheFilesAsync(EFileClearMode.ClearUnusedBundleFiles);
operation.Completed += Operation_Completed;
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
private void Operation_Completed(YooAsset.AsyncOperationBase obj)
{
_machine.ChangeState<FsmStartGame>();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d83ce785f1442a40a1ad0f837073b69
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
public class FsmCreateDownloader : IStateNode
{
private StateMachine _machine;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
PatchEventDefine.PatchStepsChange.SendEventMessage("创建资源下载器!");
CreateDownloader();
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
void CreateDownloader()
{
var packageName = (string)_machine.GetBlackboardValue("PackageName");
var package = YooAssets.GetPackage(packageName);
int downloadingMaxNum = 10;
int failedTryAgain = 3;
var downloader = package.CreateResourceDownloader(downloadingMaxNum, failedTryAgain);
_machine.SetBlackboardValue("Downloader", downloader);
if (downloader.TotalDownloadCount == 0)
{
Debug.Log("Not found any download files !");
_machine.ChangeState<FsmStartGame>();
}
else
{
// 发现新更新文件后,挂起流程系统
// 注意:开发者需要在下载前检测磁盘空间不足
int totalDownloadCount = downloader.TotalDownloadCount;
long totalDownloadBytes = downloader.TotalDownloadBytes;
PatchEventDefine.FoundUpdateFiles.SendEventMessage(totalDownloadCount, totalDownloadBytes);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b104741ebcb72946abe282c1da73360
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
using System.Collections;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
public class FsmDownloadPackageFiles : IStateNode
{
private StateMachine _machine;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
PatchEventDefine.PatchStepsChange.SendEventMessage("开始下载资源文件!");
GameManager.Instance.StartCoroutine(BeginDownload());
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
private IEnumerator BeginDownload()
{
var downloader = (ResourceDownloaderOperation)_machine.GetBlackboardValue("Downloader");
downloader.DownloadErrorCallback = PatchEventDefine.WebFileDownloadFailed.SendEventMessage;
downloader.DownloadUpdateCallback = PatchEventDefine.DownloadUpdate.SendEventMessage;
downloader.BeginDownload();
yield return downloader;
// 检测下载结果
if (downloader.Status != EOperationStatus.Succeed)
yield break;
_machine.ChangeState<FsmDownloadPackageOver>();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a3fae22040fe2d541ab4582c7c1c71fb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
internal class FsmDownloadPackageOver : IStateNode
{
private StateMachine _machine;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
PatchEventDefine.PatchStepsChange.SendEventMessage("资源文件下载完毕!");
_machine.ChangeState<FsmClearCacheBundle>();
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c96c57c65f74bb3469dc71b13ef78c84
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,154 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
internal class FsmInitializePackage : IStateNode
{
private StateMachine _machine;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
PatchEventDefine.PatchStepsChange.SendEventMessage("初始化资源包!");
GameManager.Instance.StartCoroutine(InitPackage());
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
private IEnumerator InitPackage()
{
var playMode = (EPlayMode)_machine.GetBlackboardValue("PlayMode");
var packageName = (string)_machine.GetBlackboardValue("PackageName");
// 创建资源包裹类
var package = YooAssets.TryGetPackage(packageName);
if (package == null)
package = YooAssets.CreatePackage(packageName);
// 编辑器下的模拟模式
InitializationOperation initializationOperation = null;
if (playMode == EPlayMode.EditorSimulateMode)
{
var buildResult = EditorSimulateModeHelper.SimulateBuild(packageName);
var packageRoot = buildResult.PackageRootDirectory;
var createParameters = new EditorSimulateModeParameters();
createParameters.EditorFileSystemParameters = FileSystemParameters.CreateDefaultEditorFileSystemParameters(packageRoot);
initializationOperation = package.InitializeAsync(createParameters);
}
// 单机运行模式
if (playMode == EPlayMode.OfflinePlayMode)
{
var createParameters = new OfflinePlayModeParameters();
createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
initializationOperation = package.InitializeAsync(createParameters);
}
// 联机运行模式
if (playMode == EPlayMode.HostPlayMode)
{
string defaultHostServer = GetHostServerURL();
string fallbackHostServer = GetHostServerURL();
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
var createParameters = new HostPlayModeParameters();
createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
createParameters.CacheFileSystemParameters = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices);
initializationOperation = package.InitializeAsync(createParameters);
}
// WebGL运行模式
if (playMode == EPlayMode.WebPlayMode)
{
#if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR
var createParameters = new WebPlayModeParameters();
string defaultHostServer = GetHostServerURL();
string fallbackHostServer = GetHostServerURL();
string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE"; //注意:如果有子目录,请修改此处!
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices);
initializationOperation = package.InitializeAsync(createParameters);
#else
var createParameters = new WebPlayModeParameters();
createParameters.WebServerFileSystemParameters = FileSystemParameters.CreateDefaultWebServerFileSystemParameters();
initializationOperation = package.InitializeAsync(createParameters);
#endif
}
yield return initializationOperation;
// 如果初始化失败弹出提示界面
if (initializationOperation.Status != EOperationStatus.Succeed)
{
Debug.LogWarning($"{initializationOperation.Error}");
PatchEventDefine.InitializeFailed.SendEventMessage();
}
else
{
_machine.ChangeState<FsmRequestPackageVersion>();
}
}
/// <summary>
/// 获取资源服务器地址
/// </summary>
private string GetHostServerURL()
{
//string hostServerIP = "http://10.0.2.2"; //安卓模拟器地址
string hostServerIP = "http://127.0.0.1";
string appVersion = "v1.0";
#if UNITY_EDITOR
if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android)
return $"{hostServerIP}/CDN/Android/{appVersion}";
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS)
return $"{hostServerIP}/CDN/IPhone/{appVersion}";
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL)
return $"{hostServerIP}/CDN/WebGL/{appVersion}";
else
return $"{hostServerIP}/CDN/PC/{appVersion}";
#else
if (Application.platform == RuntimePlatform.Android)
return $"{hostServerIP}/CDN/Android/{appVersion}";
else if (Application.platform == RuntimePlatform.IPhonePlayer)
return $"{hostServerIP}/CDN/IPhone/{appVersion}";
else if (Application.platform == RuntimePlatform.WebGLPlayer)
return $"{hostServerIP}/CDN/WebGL/{appVersion}";
else
return $"{hostServerIP}/CDN/PC/{appVersion}";
#endif
}
/// <summary>
/// 远端资源地址查询服务类
/// </summary>
private class RemoteServices : IRemoteServices
{
private readonly string _defaultHostServer;
private readonly string _fallbackHostServer;
public RemoteServices(string defaultHostServer, string fallbackHostServer)
{
_defaultHostServer = defaultHostServer;
_fallbackHostServer = fallbackHostServer;
}
string IRemoteServices.GetRemoteMainURL(string fileName)
{
return $"{_defaultHostServer}/{fileName}";
}
string IRemoteServices.GetRemoteFallbackURL(string fileName)
{
return $"{_fallbackHostServer}/{fileName}";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9c67e6e479b68e345afcdf325775c079
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
internal class FsmRequestPackageVersion : IStateNode
{
private StateMachine _machine;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
PatchEventDefine.PatchStepsChange.SendEventMessage("请求资源版本 !");
GameManager.Instance.StartCoroutine(UpdatePackageVersion());
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
private IEnumerator UpdatePackageVersion()
{
var packageName = (string)_machine.GetBlackboardValue("PackageName");
var package = YooAssets.GetPackage(packageName);
var operation = package.RequestPackageVersionAsync();
yield return operation;
if (operation.Status != EOperationStatus.Succeed)
{
Debug.LogWarning(operation.Error);
PatchEventDefine.PackageVersionRequestFailed.SendEventMessage();
}
else
{
Debug.Log($"Request package version : {operation.PackageVersion}");
_machine.SetBlackboardValue("PackageVersion", operation.PackageVersion);
_machine.ChangeState<FsmUpdatePackageManifest>();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5ea76dfe0fc52b47a00a3bf68a54d09
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
internal class FsmStartGame : IStateNode
{
private PatchOperation _owner;
void IStateNode.OnCreate(StateMachine machine)
{
_owner = machine.Owner as PatchOperation;
}
void IStateNode.OnEnter()
{
PatchEventDefine.PatchStepsChange.SendEventMessage("开始游戏!");
_owner.SetFinish();
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6cf80cfbed474c34b892eaeda7fcb054
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
public class FsmUpdatePackageManifest : IStateNode
{
private StateMachine _machine;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
PatchEventDefine.PatchStepsChange.SendEventMessage("更新资源清单!");
GameManager.Instance.StartCoroutine(UpdateManifest());
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
private IEnumerator UpdateManifest()
{
var packageName = (string)_machine.GetBlackboardValue("PackageName");
var packageVersion = (string)_machine.GetBlackboardValue("PackageVersion");
var package = YooAssets.GetPackage(packageName);
var operation = package.UpdatePackageManifestAsync(packageVersion);
yield return operation;
if (operation.Status != EOperationStatus.Succeed)
{
Debug.LogWarning(operation.Error);
PatchEventDefine.PackageManifestUpdateFailed.SendEventMessage();
yield break;
}
else
{
_machine.ChangeState<FsmCreateDownloader>();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13faaa12de67f5e4db31cd8a44563089
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,102 @@
using UnityEngine;
using UniFramework.Machine;
using UniFramework.Event;
using YooAsset;
public class PatchOperation : GameAsyncOperation
{
private enum ESteps
{
None,
Update,
Done,
}
private readonly EventGroup _eventGroup = new EventGroup();
private readonly StateMachine _machine;
private readonly string _packageName;
private ESteps _steps = ESteps.None;
public PatchOperation(string packageName, EPlayMode playMode)
{
_packageName = packageName;
// 注册监听事件
_eventGroup.AddListener<UserEventDefine.UserTryInitialize>(OnHandleEventMessage);
_eventGroup.AddListener<UserEventDefine.UserBeginDownloadWebFiles>(OnHandleEventMessage);
_eventGroup.AddListener<UserEventDefine.UserTryRequestPackageVersion>(OnHandleEventMessage);
_eventGroup.AddListener<UserEventDefine.UserTryUpdatePackageManifest>(OnHandleEventMessage);
_eventGroup.AddListener<UserEventDefine.UserTryDownloadWebFiles>(OnHandleEventMessage);
// 创建状态机
_machine = new StateMachine(this);
_machine.AddNode<FsmInitializePackage>();
_machine.AddNode<FsmRequestPackageVersion>();
_machine.AddNode<FsmUpdatePackageManifest>();
_machine.AddNode<FsmCreateDownloader>();
_machine.AddNode<FsmDownloadPackageFiles>();
_machine.AddNode<FsmDownloadPackageOver>();
_machine.AddNode<FsmClearCacheBundle>();
_machine.AddNode<FsmStartGame>();
_machine.SetBlackboardValue("PackageName", packageName);
_machine.SetBlackboardValue("PlayMode", playMode);
}
protected override void OnStart()
{
_steps = ESteps.Update;
_machine.Run<FsmInitializePackage>();
}
protected override void OnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.Update)
{
_machine.Update();
}
}
protected override void OnAbort()
{
}
public void SetFinish()
{
_steps = ESteps.Done;
_eventGroup.RemoveAllListener();
Status = EOperationStatus.Succeed;
Debug.Log($"Package {_packageName} patch done !");
}
/// <summary>
/// 接收事件
/// </summary>
private void OnHandleEventMessage(IEventMessage message)
{
if (message is UserEventDefine.UserTryInitialize)
{
_machine.ChangeState<FsmInitializePackage>();
}
else if (message is UserEventDefine.UserBeginDownloadWebFiles)
{
_machine.ChangeState<FsmDownloadPackageFiles>();
}
else if (message is UserEventDefine.UserTryRequestPackageVersion)
{
_machine.ChangeState<FsmRequestPackageVersion>();
}
else if (message is UserEventDefine.UserTryUpdatePackageManifest)
{
_machine.ChangeState<FsmUpdatePackageManifest>();
}
else if (message is UserEventDefine.UserTryDownloadWebFiles)
{
_machine.ChangeState<FsmCreateDownloader>();
}
else
{
throw new System.NotImplementedException($"{message.GetType()}");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c1b4cadd806a1a409db720564a44a83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,183 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UniFramework.Event;
public class PatchWindow : MonoBehaviour
{
/// <summary>
/// 对话框封装类
/// </summary>
private class MessageBox
{
private GameObject _cloneObject;
private Text _content;
private Button _btnOK;
private System.Action _clickOK;
public bool ActiveSelf
{
get
{
return _cloneObject.activeSelf;
}
}
public void Create(GameObject cloneObject)
{
_cloneObject = cloneObject;
_content = cloneObject.transform.Find("txt_content").GetComponent<Text>();
_btnOK = cloneObject.transform.Find("btn_ok").GetComponent<Button>();
_btnOK.onClick.AddListener(OnClickYes);
}
public void Show(string content, System.Action clickOK)
{
_content.text = content;
_clickOK = clickOK;
_cloneObject.SetActive(true);
_cloneObject.transform.SetAsLastSibling();
}
public void Hide()
{
_content.text = string.Empty;
_clickOK = null;
_cloneObject.SetActive(false);
}
private void OnClickYes()
{
_clickOK?.Invoke();
Hide();
}
}
private readonly EventGroup _eventGroup = new EventGroup();
private readonly List<MessageBox> _msgBoxList = new List<MessageBox>();
// UGUI相关
private GameObject _messageBoxObj;
private Slider _slider;
private Text _tips;
void Awake()
{
_slider = transform.Find("UIWindow/Slider").GetComponent<Slider>();
_tips = transform.Find("UIWindow/Slider/txt_tips").GetComponent<Text>();
_tips.text = "Initializing the game world !";
_messageBoxObj = transform.Find("UIWindow/MessgeBox").gameObject;
_messageBoxObj.SetActive(false);
_eventGroup.AddListener<PatchEventDefine.InitializeFailed>(OnHandleEventMessage);
_eventGroup.AddListener<PatchEventDefine.PatchStepsChange>(OnHandleEventMessage);
_eventGroup.AddListener<PatchEventDefine.FoundUpdateFiles>(OnHandleEventMessage);
_eventGroup.AddListener<PatchEventDefine.DownloadUpdate>(OnHandleEventMessage);
_eventGroup.AddListener<PatchEventDefine.PackageVersionRequestFailed>(OnHandleEventMessage);
_eventGroup.AddListener<PatchEventDefine.PackageManifestUpdateFailed>(OnHandleEventMessage);
_eventGroup.AddListener<PatchEventDefine.WebFileDownloadFailed>(OnHandleEventMessage);
}
void OnDestroy()
{
_eventGroup.RemoveAllListener();
}
/// <summary>
/// 接收事件
/// </summary>
private void OnHandleEventMessage(IEventMessage message)
{
if (message is PatchEventDefine.InitializeFailed)
{
System.Action callback = () =>
{
UserEventDefine.UserTryInitialize.SendEventMessage();
};
ShowMessageBox($"Failed to initialize package !", callback);
}
else if (message is PatchEventDefine.PatchStepsChange)
{
var msg = message as PatchEventDefine.PatchStepsChange;
_tips.text = msg.Tips;
UnityEngine.Debug.Log(msg.Tips);
}
else if (message is PatchEventDefine.FoundUpdateFiles)
{
var msg = message as PatchEventDefine.FoundUpdateFiles;
System.Action callback = () =>
{
UserEventDefine.UserBeginDownloadWebFiles.SendEventMessage();
};
float sizeMB = msg.TotalSizeBytes / 1048576f;
sizeMB = Mathf.Clamp(sizeMB, 0.1f, float.MaxValue);
string totalSizeMB = sizeMB.ToString("f1");
ShowMessageBox($"Found update patch files, Total count {msg.TotalCount} Total szie {totalSizeMB}MB", callback);
}
else if (message is PatchEventDefine.DownloadUpdate)
{
var msg = message as PatchEventDefine.DownloadUpdate;
_slider.value = (float)msg.CurrentDownloadCount / msg.TotalDownloadCount;
string currentSizeMB = (msg.CurrentDownloadSizeBytes / 1048576f).ToString("f1");
string totalSizeMB = (msg.TotalDownloadSizeBytes / 1048576f).ToString("f1");
_tips.text = $"{msg.CurrentDownloadCount}/{msg.TotalDownloadCount} {currentSizeMB}MB/{totalSizeMB}MB";
}
else if (message is PatchEventDefine.PackageVersionRequestFailed)
{
System.Action callback = () =>
{
UserEventDefine.UserTryRequestPackageVersion.SendEventMessage();
};
ShowMessageBox($"Failed to request package version, please check the network status.", callback);
}
else if (message is PatchEventDefine.PackageManifestUpdateFailed)
{
System.Action callback = () =>
{
UserEventDefine.UserTryUpdatePackageManifest.SendEventMessage();
};
ShowMessageBox($"Failed to update patch manifest, please check the network status.", callback);
}
else if (message is PatchEventDefine.WebFileDownloadFailed)
{
var msg = message as PatchEventDefine.WebFileDownloadFailed;
System.Action callback = () =>
{
UserEventDefine.UserTryDownloadWebFiles.SendEventMessage();
};
ShowMessageBox($"Failed to download file : {msg.FileName}", callback);
}
else
{
throw new System.NotImplementedException($"{message.GetType()}");
}
}
/// <summary>
/// 显示对话框
/// </summary>
private void ShowMessageBox(string content, System.Action ok)
{
// 尝试获取一个可用的对话框
MessageBox msgBox = null;
for (int i = 0; i < _msgBoxList.Count; i++)
{
var item = _msgBoxList[i];
if (item.ActiveSelf == false)
{
msgBox = item;
break;
}
}
// 如果没有可用的对话框,则创建一个新的对话框
if (msgBox == null)
{
msgBox = new MessageBox();
var cloneObject = GameObject.Instantiate(_messageBoxObj, _messageBoxObj.transform.parent);
msgBox.Create(cloneObject);
_msgBoxList.Add(msgBox);
}
// 显示对话框
msgBox.Show(content, ok);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c569e2dd13155914aa41a50e0e588b6d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fadb6c5775042624595410d325420148
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UIAboutWindow : MonoBehaviour
{
private void Awake()
{
var maskBtn = this.transform.Find("mask").GetComponent<Button>();
maskBtn.onClick.AddListener(OnClicMaskBtn);
}
private void OnClicMaskBtn()
{
GameObject.Destroy(this.gameObject);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8e24fc68d39841044901f3df71616040
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,53 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UniFramework.Event;
public class UIBattleWindow : MonoBehaviour
{
private readonly EventGroup _eventGroup = new EventGroup();
private GameObject _overView;
private Text _scoreLabel;
private void Awake()
{
_overView = this.transform.Find("OverView").gameObject;
_scoreLabel = this.transform.Find("ScoreView/Score").GetComponent<Text>();
_scoreLabel.text = "Score : 0";
var restartBtn = this.transform.Find("OverView/ReplayButton").GetComponent<Button>();
restartBtn.onClick.AddListener(OnClickReplayBtn);
var homeBtn = this.transform.Find("OverView/HomeButton").GetComponent<Button>();
homeBtn.onClick.AddListener(OnClickHomeBtn);
_eventGroup.AddListener<BattleEventDefine.ScoreChange>(OnHandleEventMessage);
_eventGroup.AddListener<BattleEventDefine.GameOver>(OnHandleEventMessage);
}
private void OnDestroy()
{
_eventGroup.RemoveAllListener();
}
private void OnClickReplayBtn()
{
SceneEventDefine.ChangeToBattleScene.SendEventMessage();
}
private void OnClickHomeBtn()
{
SceneEventDefine.ChangeToHomeScene.SendEventMessage();
}
private void OnHandleEventMessage(IEventMessage message)
{
if(message is BattleEventDefine.ScoreChange)
{
var msg = message as BattleEventDefine.ScoreChange;
_scoreLabel.text = $"Score : {msg.CurrentScores}";
}
else if(message is BattleEventDefine.GameOver)
{
_overView.SetActive(true);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9776c197a7f86e94c9484946495616bb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UIHomeWindow : MonoBehaviour
{
private Text _version;
private GameObject _aboutView;
private void Awake()
{
_version = this.transform.Find("version").GetComponent<Text>();
_aboutView = this.transform.Find("AboutView").gameObject;
var loginBtn = this.transform.Find("PlayGameButton").GetComponent<Button>();
loginBtn.onClick.AddListener(OnClickPlayGameBtn);
var aboutBtn = this.transform.Find("AboutButton").GetComponent<Button>();
aboutBtn.onClick.AddListener(OnClicAboutBtn);
var maskBtn = this.transform.Find("AboutView/mask").GetComponent<Button>();
maskBtn.onClick.AddListener(OnClickMaskBtn);
}
private void Start()
{
var package = YooAsset.YooAssets.GetPackage("DefaultPackage");
_version.text = "Version : " + package.GetPackageVersion();
}
private void OnClickPlayGameBtn()
{
SceneEventDefine.ChangeToBattleScene.SendEventMessage();
}
private void OnClicAboutBtn()
{
_aboutView.SetActive(true);
}
private void OnClickMaskBtn()
{
_aboutView.SetActive(false);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4792d7c57be85c845bc50d7215160853
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UniFramework.Utility;
public class UILoadingWindow : MonoBehaviour
{
private readonly UniTimer _timer = UniTimer.CreatePepeatTimer(0, 0.2f);
private Text _info;
private int _countdown;
private void Awake()
{
_info = this.transform.Find("info").GetComponent<Text>();
}
private void Start()
{
_info.text = "Loading";
_timer.Reset();
_countdown = 0;
}
private void Update()
{
if (_timer.Update(Time.deltaTime))
{
_countdown++;
if (_countdown > 6)
_countdown = 0;
string tips = "Loading";
for (int i = 0; i < _countdown; i++)
{
tips += ".";
}
_info.text = tips;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f2bfcc4f450a0b94bb7748fb4788630e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: