Demo
This commit is contained in:
ALEXTANG
2023-05-13 11:57:11 +08:00
parent fd7d8a798b
commit 7bf081269c
313 changed files with 135421 additions and 2 deletions

View File

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

View File

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

View File

@@ -0,0 +1,15 @@
using TEngine;
namespace GameLogic
{
public static class ActorEventDefine
{
public static readonly int ScoreChange = StringId.StringToHash("ActorEventDefine.ScoreChange");
public static readonly int GameOver = StringId.StringToHash("ActorEventDefine.GameOver");
public static readonly int EnemyDead = StringId.StringToHash("ActorEventDefine.EnemyDead");
public static readonly int PlayerDead = StringId.StringToHash("ActorEventDefine.PlayerDead");
public static readonly int AsteroidExplosion = StringId.StringToHash("ActorEventDefine.AsteroidExplosion");
public static readonly int EnemyFireBullet = StringId.StringToHash("ActorEventDefine.EnemyFireBullet");
public static readonly int PlayerFireBullet = StringId.StringToHash("ActorEventDefine.PlayerFireBullet");
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: de011fa2ea744cfe94ddb63030ebf031
timeCreated: 1683946273

View File

@@ -0,0 +1,45 @@
using GameLogic;
using TEngine;
using UnityEngine;
using UniFramework.Pooling;
public class EntityAsteroid : MonoBehaviour
{
public float MoveSpeed = -5f;
public float Tumble = 5f;
private SpawnHandle _handle;
private Rigidbody _rigidbody;
public void InitEntity(SpawnHandle handle)
{
_handle = handle;
_rigidbody.velocity = this.transform.forward * MoveSpeed;
_rigidbody.angularVelocity = Random.insideUnitSphere * Tumble;
}
void Awake()
{
_rigidbody = this.transform.GetComponent<Rigidbody>();
}
void OnTriggerEnter(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("player"))
{
GameEvent.Send(ActorEventDefine.AsteroidExplosion,this.transform.position, this.transform.rotation);
_handle.Restore();
_handle = null;
}
}
void OnTriggerExit(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("Boundary"))
{
_handle.Restore();
_handle = null;
}
}
}

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,56 @@
using UnityEngine;
using UniFramework.Pooling;
public class EntityBullet : MonoBehaviour
{
public float MoveSpeed = 20f;
public float DelayDestroyTime = 5f;
private SpawnHandle _handle;
private Rigidbody _rigidbody;
public void InitEntity(SpawnHandle handle)
{
_handle = handle;
_rigidbody.velocity = this.transform.forward * MoveSpeed;
}
void Awake()
{
_rigidbody = this.transform.GetComponent<Rigidbody>();
}
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)
{
_handle.Restore();
_handle = null;
}
}
if (goName.StartsWith("player_bullet"))
{
if (name.StartsWith("player") == false)
{
_handle.Restore();
_handle = null;
}
}
}
void OnTriggerExit(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("Boundary"))
{
_handle.Restore();
_handle = null;
}
}
}

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,21 @@
using UnityEngine;
using UniFramework.Pooling;
public class EntityEffect : MonoBehaviour
{
public float DelayDestroyTime = 1f;
private SpawnHandle _handle;
public void InitEntity(SpawnHandle handle)
{
_handle = handle;
Invoke(nameof(DelayDestroy), DelayDestroyTime);
}
private void DelayDestroy()
{
_handle.Restore();
_handle = null;
}
}

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,101 @@
using System.Collections;
using GameLogic;
using TEngine;
using UnityEngine;
using UniFramework.Pooling;
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 SpawnHandle _handle;
private Transform _shotSpawn;
private Rigidbody _rigidbody;
private AudioSource _audioSource;
private float _lastFireTime = 0f;
private float _currentSpeed;
private float _targetManeuver;
public void InitEntity(SpawnHandle handle)
{
_handle = handle;
_rigidbody.velocity = this.transform.forward * -5f;
_lastFireTime = Time.time;
_currentSpeed = _rigidbody.velocity.z;
_targetManeuver = 0f;
StartCoroutine(Evade());
}
void Awake()
{
_rigidbody = this.gameObject.GetComponent<Rigidbody>();
_audioSource = this.gameObject.GetComponent<AudioSource>();
_shotSpawn = this.transform.Find("shot_spawn");
}
void Update()
{
if (Time.time - _lastFireTime >= FireInterval)
{
_lastFireTime = Time.time;
_audioSource.Play();
GameEvent.Send(ActorEventDefine.EnemyFireBullet,this._shotSpawn.position, this._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"))
{
GameEvent.Send(ActorEventDefine.EnemyDead,this.transform.position, this.transform.rotation);
_handle.Restore();
_handle = null;
}
}
void OnTriggerExit(Collider other)
{
var name = other.gameObject.name;
if (name.StartsWith("Boundary"))
{
_handle.Restore();
_handle = null;
}
}
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,65 @@
using GameLogic;
using TEngine;
using UnityEngine;
using UniFramework.Pooling;
public class EntityPlayer : MonoBehaviour
{
public RoomBoundary Boundary;
public float MoveSpeed = 10f;
public float FireRate = 0.25f;
private SpawnHandle _handle;
private float _nextFireTime = 0f;
private Transform _shotSpawn;
private Rigidbody _rigidbody;
private AudioSource _audioSource;
public void InitEntity(SpawnHandle handle)
{
_handle = handle;
}
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();
GameEvent.Send(ActorEventDefine.PlayerFireBullet,_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"))
{
GameEvent.Send(ActorEventDefine.PlayerDead,transform.position, transform.rotation);
_handle.Restore();
_handle = null;
}
}
}

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,10 @@
using System;
namespace GameLogic
{
[Serializable]
public class RoomBoundary
{
public float xMin, xMax, zMin, zMax;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 871ee1492e44425da07021fdc3100325
timeCreated: 1683946064

View File

@@ -0,0 +1,239 @@
using System.Collections;
using GameLogic;
using TEngine;
using UnityEngine;
using UniFramework.Pooling;
using UniFramework.Utility;
using AudioType = TEngine.AudioType;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
/// <summary>
/// 战斗房间
/// </summary>
public class BattleRoom
{
private enum ESteps
{
None,
Ready,
Spawn,
WaitSpawn,
WaitWave,
GameOver,
}
private Spawner _entitySpawner;
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 UniTimer _startWaitTimer = UniTimer.CreateOnceTimer(1f);
private UniTimer _spawnWaitTimer = UniTimer.CreateOnceTimer(0.75f);
private UniTimer _waveWaitTimer = UniTimer.CreateOnceTimer(4f);
public BattleRoom()
{
Utility.Unity.AddUpdateListener(UpdateRoom);
}
~BattleRoom()
{
Utility.Unity.RemoveUpdateListener(UpdateRoom);
DestroyRoom();
}
/// <summary>
/// 销毁房间
/// </summary>
public void DestroyRoom()
{
// 加载背景音乐
GameModule.Audio.Stop(AudioType.Music, true);
if (_entitySpawner != null)
_entitySpawner.DestroyAll(true);
if (_roomRoot != null)
Object.Destroy(_roomRoot);
GameModule.UI.CloseWindow<UIBattleWindow>();
}
/// <summary>
/// 更新房间
/// </summary>
public void UpdateRoom()
{
if (_steps == ESteps.None || _steps == ESteps.GameOver)
return;
if (_steps == ESteps.Ready)
{
if (_startWaitTimer.Update(Time.deltaTime))
{
_steps = ESteps.Spawn;
}
}
if (_steps == ESteps.Spawn)
{
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;
if (enemyLocation == "enemy_ship")
{
// 生成敌人实体
var handle = _entitySpawner.SpawnSync(enemyLocation, _roomRoot.transform, spawnPosition, spawnRotation);
var entity = handle.GameObj.GetComponent<EntityEnemy>();
entity.InitEntity(handle);
}
else
{
// 生成小行星实体
var handle = _entitySpawner.SpawnSync(enemyLocation, _roomRoot.transform, spawnPosition, spawnRotation);
var entity = handle.GameObj.GetComponent<EntityAsteroid>();
entity.InitEntity(handle);
}
_waveSpawnCount++;
if (_waveSpawnCount >= EnemyCount)
{
_steps = ESteps.WaitWave;
}
else
{
_steps = ESteps.WaitSpawn;
}
}
if (_steps == ESteps.WaitSpawn)
{
if (_spawnWaitTimer.Update(Time.deltaTime))
{
_spawnWaitTimer.Reset();
_steps = ESteps.Spawn;
}
}
if (_steps == ESteps.WaitWave)
{
if (_waveWaitTimer.Update(Time.deltaTime))
{
_waveWaitTimer.Reset();
_waveSpawnCount = 0;
_steps = ESteps.Spawn;
}
}
}
/// <summary>
/// 加载房间
/// </summary>
public IEnumerator LoadRoom()
{
// 创建房间根对象
_roomRoot = new GameObject("BattleRoom");
// 加载背景音乐
GameModule.Audio.Play(AudioType.Music, "music_background", true);
// 创建游戏对象发生器
_entitySpawner = UniPooling.CreateSpawner("DefaultPackage");
// 创建游戏对象池
yield return _entitySpawner.CreateGameObjectPoolAsync("player_ship");
yield return _entitySpawner.CreateGameObjectPoolAsync("player_bullet");
yield return _entitySpawner.CreateGameObjectPoolAsync("enemy_ship");
yield return _entitySpawner.CreateGameObjectPoolAsync("enemy_bullet");
yield return _entitySpawner.CreateGameObjectPoolAsync("asteroid01");
yield return _entitySpawner.CreateGameObjectPoolAsync("asteroid02");
yield return _entitySpawner.CreateGameObjectPoolAsync("asteroid03");
yield return _entitySpawner.CreateGameObjectPoolAsync("explosion_asteroid");
yield return _entitySpawner.CreateGameObjectPoolAsync("explosion_enemy");
yield return _entitySpawner.CreateGameObjectPoolAsync("explosion_player");
// 创建玩家实体对象
var handle = _entitySpawner.SpawnSync("player_ship", _roomRoot.transform);
var entity = handle.GameObj.GetComponent<EntityPlayer>();
entity.InitEntity(handle);
// 显示战斗界面
yield return GameModule.UI.ShowUIAsync<UIBattleWindow>();
// 监听游戏事件
GameEvent.AddEventListener<Vector3,Quaternion>(ActorEventDefine.PlayerDead,OnPlayerDead);
GameEvent.AddEventListener<Vector3,Quaternion>(ActorEventDefine.EnemyDead,OnEnemyDead);
GameEvent.AddEventListener<Vector3,Quaternion>(ActorEventDefine.AsteroidExplosion,OnAsteroidExplosion);
GameEvent.AddEventListener<Vector3,Quaternion>(ActorEventDefine.PlayerFireBullet,OnPlayerFireBullet);
GameEvent.AddEventListener<Vector3,Quaternion>(ActorEventDefine.EnemyFireBullet,OnEnemyFireBullet);
_steps = ESteps.Ready;
}
#region
private void OnPlayerDead(Vector3 position,Quaternion rotation)
{
// 创建爆炸效果
var handle = _entitySpawner.SpawnSync("explosion_player", _roomRoot.transform, position, rotation);
var entity = handle.GameObj.GetComponent<EntityEffect>();
entity.InitEntity(handle);
_steps = ESteps.GameOver;
GameEvent.Send(ActorEventDefine.GameOver);
}
private void OnEnemyDead(Vector3 position,Quaternion rotation)
{
// 创建爆炸效果
var handle = _entitySpawner.SpawnSync("explosion_enemy", _roomRoot.transform, position, rotation);
var entity = handle.GameObj.GetComponent<EntityEffect>();
entity.InitEntity(handle);
_totalScore += EnemyScore;
GameEvent.Send(ActorEventDefine.ScoreChange,_totalScore);
}
private void OnAsteroidExplosion(Vector3 position,Quaternion rotation)
{
// 创建爆炸效果
var handle = _entitySpawner.SpawnSync("explosion_asteroid", _roomRoot.transform, position, rotation);
var entity = handle.GameObj.GetComponent<EntityEffect>();
entity.InitEntity(handle);
_totalScore += AsteroidScore;
GameEvent.Send(ActorEventDefine.ScoreChange,_totalScore);
}
private void OnPlayerFireBullet(Vector3 position,Quaternion rotation)
{
// 创建子弹实体
var handle = _entitySpawner.SpawnSync("player_bullet", _roomRoot.transform, position, rotation);
var entity = handle.GameObj.GetComponent<EntityBullet>();
entity.InitEntity(handle);
}
private void OnEnemyFireBullet(Vector3 position,Quaternion rotation)
{
// 创建子弹实体
var handle = _entitySpawner.SpawnSync("enemy_bullet", _roomRoot.transform,position,rotation);
var entity = handle.GameObj.GetComponent<EntityBullet>();
entity.InitEntity(handle);
}
#endregion
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f4289f2d6df7432ca3f04870400571df
timeCreated: 1683946643

View File

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

View File

@@ -0,0 +1,15 @@
using System;
using UnityEngine;
using YooAsset;
public class BhvApplicationQuit : MonoBehaviour
{
private void Awake()
{
DontDestroyOnLoad(this.gameObject);
}
private void OnApplicationQuit()
{
YooAssets.Destroy();
}
}

View File

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

View File

@@ -0,0 +1,21 @@
using System;
using UnityEngine;
public class BhvBackgroundScroller : 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,3 @@
fileFormatVersion: 2
guid: 5119c9cc1ae24e3e8272dc88a33b8ede
timeCreated: 1683947325

View File

@@ -0,0 +1,79 @@
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using TEngine;
namespace GameLogic
{
[Window(UILayer.UI)]
class UIBattleWindow : UIWindow
{
#region
private Text m_textScore;
private GameObject m_goOverView;
private Button m_btnRestart;
private Button m_btnHome;
public override void ScriptGenerator()
{
m_textScore = FindChildComponent<Text>("ScoreView/m_textScore");
m_goOverView = FindChild("m_goOverView").gameObject;
m_btnRestart = FindChildComponent<Button>("m_goOverView/m_btnRestart");
m_btnHome = FindChildComponent<Button>("m_goOverView/m_btnHome");
m_btnRestart.onClick.AddListener(UniTask.UnityAction(OnClickRestartBtn));
m_btnHome.onClick.AddListener(UniTask.UnityAction(OnClickHomeBtn));
}
#endregion
public override void RegisterEvent()
{
AddUIEvent<int>(ActorEventDefine.ScoreChange, OnScoreChange);
AddUIEvent(ActorEventDefine.GameOver, OnGameOver);
}
public override void OnRefresh()
{
m_goOverView.SetActive(false);
}
#region
private async UniTaskVoid OnClickRestartBtn()
{
await UniTask.Yield();
// yield return YooAssets.LoadSceneAsync("scene_battle");
//
// _battleRoom = new BattleRoom();
// yield return _battleRoom.LoadRoom();
//
// // 释放资源
// var package = YooAssets.GetPackage("DefaultPackage");
// package.UnloadUnusedAssets();
}
private async UniTaskVoid OnClickHomeBtn()
{
await UniTask.Yield();
// yield return YooAssets.LoadSceneAsync("scene_home");
// yield return UniWindow.OpenWindowAsync<UIHomeWindow>("UIHome");
//
// // 释放资源
// var package = YooAssets.GetPackage("DefaultPackage");
// package.UnloadUnusedAssets();
}
#endregion
private void OnScoreChange(int currentScores)
{
m_textScore.text = $"Score : {currentScores}";
}
private void OnGameOver()
{
m_goOverView.SetActive(true);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 15d6c65ac046403185b3dd833e6e2a7e
timeCreated: 1683947329

View File

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

View File

@@ -0,0 +1,36 @@
# UniFramework.Pooling
一个功能强大的游戏对象池系统。
该系统依赖于YooAsset资源系统支持各类异步编程支持同步接口和异步接口。
```c#
using UnityEngine;
using YooAsset;
using UniFramework.Pooling;
IEnumerator Start()
{
// 初始化游戏对象池系统
UniPooling.Initalize();
// 创建孵化器
var spawner = UniPooling.CreateSpawner("DefaultPackage");
// 创建Cube预制体的对象池
var operation = spawner.CreateGameObjectPoolAsync("Cube.prefab");
yield return operation;
// 孵化Cube游戏对象
SpawnHandle handle = spawner.SpawnAsync("Cube.prefab");
yield return handle;
Debug.Log(handle.GameObj.name);
// 回收游戏对象
handle.Restore();
// 丢弃游戏对象
handle.Discard();
}
```

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7976cbcaa4dcfcc4b932fb01d6c0499a
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,70 @@
using YooAsset;
namespace UniFramework.Pooling
{
public class CreatePoolOperation : GameAsyncOperation
{
private enum ESteps
{
None,
Waiting,
Done,
}
private readonly AssetOperationHandle _handle;
private ESteps _steps = ESteps.None;
internal CreatePoolOperation(AssetOperationHandle handle)
{
_handle = handle;
}
protected override void OnStart()
{
_steps = ESteps.Waiting;
}
protected override void OnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.Waiting)
{
if (_handle.IsValid == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{nameof(AssetOperationHandle)} is invalid.";
return;
}
if (_handle.IsDone == false)
return;
if (_handle.AssetObject == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{nameof(AssetOperationHandle.AssetObject)} is null.";
return;
}
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
/// <summary>
/// 等待异步实例化结束
/// </summary>
public void WaitForAsyncComplete()
{
if (_handle != null)
{
if (_steps == ESteps.Done)
return;
_handle.WaitForAsyncComplete();
OnUpdate();
}
}
}
}

View File

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

View File

@@ -0,0 +1,215 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
namespace UniFramework.Pooling
{
internal class GameObjectPool
{
private readonly Transform _poolRoot;
private readonly Queue<InstantiateOperation> _cacheOperations;
private readonly bool _dontDestroy;
private readonly int _initCapacity;
private readonly int _maxCapacity;
private readonly float _destroyTime;
private float _lastRestoreRealTime = -1f;
/// <summary>
/// 资源句柄
/// </summary>
public AssetOperationHandle AssetHandle { private set; get; }
/// <summary>
/// 资源定位地址
/// </summary>
public string Location { private set; get; }
/// <summary>
/// 内部缓存总数
/// </summary>
public int CacheCount
{
get { return _cacheOperations.Count; }
}
/// <summary>
/// 外部使用总数
/// </summary>
public int SpawnCount { private set; get; } = 0;
/// <summary>
/// 是否常驻不销毁
/// </summary>
public bool DontDestroy
{
get { return _dontDestroy; }
}
public GameObjectPool(GameObject poolRoot, string location, bool dontDestroy, int initCapacity, int maxCapacity, float destroyTime)
{
_poolRoot = poolRoot.transform;
Location = location;
_dontDestroy = dontDestroy;
_initCapacity = initCapacity;
_maxCapacity = maxCapacity;
_destroyTime = destroyTime;
// 创建缓存池
_cacheOperations = new Queue<InstantiateOperation>(initCapacity);
}
/// <summary>
/// 创建对象池
/// </summary>
public void CreatePool(ResourcePackage package)
{
// 加载游戏对象
AssetHandle = package.LoadAssetAsync<GameObject>(Location);
// 创建初始对象
for (int i = 0; i < _initCapacity; i++)
{
var operation = AssetHandle.InstantiateAsync(_poolRoot);
_cacheOperations.Enqueue(operation);
}
}
/// <summary>
/// 销毁游戏对象池
/// </summary>
public void DestroyPool()
{
// 卸载资源对象
AssetHandle.Release();
AssetHandle = null;
// 销毁游戏对象
foreach (var operation in _cacheOperations)
{
if (operation.Result != null)
GameObject.Destroy(operation.Result);
}
_cacheOperations.Clear();
SpawnCount = 0;
}
/// <summary>
/// 查询静默时间内是否可以销毁
/// </summary>
public bool CanAutoDestroy()
{
if (_dontDestroy)
return false;
if (_destroyTime < 0)
return false;
if (_lastRestoreRealTime > 0 && SpawnCount <= 0)
return (Time.realtimeSinceStartup - _lastRestoreRealTime) > _destroyTime;
else
return false;
}
/// <summary>
/// 游戏对象池是否已经销毁
/// </summary>
public bool IsDestroyed()
{
return AssetHandle == null;
}
/// <summary>
/// 回收
/// </summary>
public void Restore(InstantiateOperation operation)
{
if (IsDestroyed())
{
DestroyInstantiateOperation(operation);
return;
}
SpawnCount--;
if (SpawnCount <= 0)
_lastRestoreRealTime = Time.realtimeSinceStartup;
// 如果外部逻辑销毁了游戏对象
if (operation.Status == EOperationStatus.Succeed)
{
if (operation.Result == null)
return;
}
// 如果缓存池还未满员
if (_cacheOperations.Count < _maxCapacity)
{
SetRestoreGameObject(operation.Result);
_cacheOperations.Enqueue(operation);
}
else
{
DestroyInstantiateOperation(operation);
}
}
/// <summary>
/// 丢弃
/// </summary>
public void Discard(InstantiateOperation operation)
{
if (IsDestroyed())
{
DestroyInstantiateOperation(operation);
return;
}
SpawnCount--;
if (SpawnCount <= 0)
_lastRestoreRealTime = Time.realtimeSinceStartup;
DestroyInstantiateOperation(operation);
}
/// <summary>
/// 获取一个游戏对象
/// </summary>
public SpawnHandle Spawn(Transform parent, Vector3 position, Quaternion rotation, bool forceClone, params System.Object[] userDatas)
{
InstantiateOperation operation;
if (forceClone == false && _cacheOperations.Count > 0)
operation = _cacheOperations.Dequeue();
else
operation = AssetHandle.InstantiateAsync();
SpawnCount++;
SpawnHandle handle = new SpawnHandle(this, operation, parent, position, rotation, userDatas);
YooAssets.StartOperation(handle);
return handle;
}
private void DestroyInstantiateOperation(InstantiateOperation operation)
{
// 取消异步操作
operation.Cancel();
// 销毁游戏对象
if (operation.Result != null)
{
GameObject.Destroy(operation.Result);
}
}
private void SetRestoreGameObject(GameObject gameObj)
{
if (gameObj != null)
{
gameObj.SetActive(false);
gameObj.transform.SetParent(_poolRoot);
gameObj.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
}
}
}
}

View File

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

View File

@@ -0,0 +1,148 @@
using UnityEngine;
using YooAsset;
namespace UniFramework.Pooling
{
public sealed class SpawnHandle : GameAsyncOperation
{
private enum ESteps
{
None,
Waiting,
Done,
}
private readonly GameObjectPool _pool;
private InstantiateOperation _operation;
private readonly Transform _parent;
private readonly Vector3 _position;
private readonly Quaternion _rotation;
private ESteps _steps = ESteps.None;
/// <summary>
/// 实例化的游戏对象
/// </summary>
public GameObject GameObj
{
get
{
if (_operation == null)
{
UniLogger.Warning("The spawn handle is invalid !");
return null;
}
return _operation.Result;
}
}
/// <summary>
/// 用户自定义数据集
/// </summary>
public System.Object[] UserDatas { private set; get; }
private SpawnHandle()
{
}
internal SpawnHandle(GameObjectPool pool, InstantiateOperation operation, Transform parent, Vector3 position, Quaternion rotation, params System.Object[] userDatas)
{
_pool = pool;
_operation = operation;
_parent = parent;
_position = position;
_rotation = rotation;
UserDatas = userDatas;
}
protected override void OnStart()
{
_steps = ESteps.Waiting;
}
protected override void OnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.Waiting)
{
if (_operation.IsDone == false)
return;
if (_operation.Status != EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _operation.Error;
return;
}
if (_operation.Result == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Clone game object is null.";
return;
}
// 设置参数
_operation.Result.transform.SetParent(_parent);
_operation.Result.transform.SetPositionAndRotation(_position, _rotation);
_operation.Result.SetActive(true);
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
/// <summary>
/// 回收
/// </summary>
public void Restore()
{
if (_operation != null)
{
ClearCompletedCallback();
CancelHandle();
_pool.Restore(_operation);
_operation = null;
}
}
/// <summary>
/// 丢弃
/// </summary>
public void Discard()
{
if (_operation != null)
{
ClearCompletedCallback();
CancelHandle();
_pool.Discard(_operation);
_operation = null;
}
}
/// <summary>
/// 等待异步实例化结束
/// </summary>
public void WaitForAsyncComplete()
{
if (_operation != null)
{
if (_steps == ESteps.Done)
return;
_operation.WaitForAsyncComplete();
OnUpdate();
}
}
private void CancelHandle()
{
if (IsDone == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"User cancelled !";
}
}
}
}

View File

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

View File

@@ -0,0 +1,259 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
namespace UniFramework.Pooling
{
public class Spawner
{
private readonly List<GameObjectPool> _gameObjectPools = new List<GameObjectPool>(100);
private readonly List<GameObjectPool> _removeList = new List<GameObjectPool>(100);
private readonly GameObject _spawnerRoot;
private readonly ResourcePackage _package;
public string PackageName
{
get
{
return _package.PackageName;
}
}
private Spawner()
{
}
internal Spawner(GameObject poolingRoot, ResourcePackage package)
{
_spawnerRoot = new GameObject($"{package.PackageName}");
_spawnerRoot.transform.SetParent(poolingRoot.transform);
_package = package;
}
/// <summary>
/// 更新游戏对象池系统
/// </summary>
internal void Update()
{
_removeList.Clear();
foreach (var pool in _gameObjectPools)
{
if (pool.CanAutoDestroy())
_removeList.Add(pool);
}
foreach (var pool in _removeList)
{
_gameObjectPools.Remove(pool);
pool.DestroyPool();
}
}
/// <summary>
/// 销毁游戏对象池系统
/// </summary>
internal void Destroy()
{
DestroyAll(true);
}
/// <summary>
/// 销毁所有对象池及其资源
/// </summary>
/// <param name="includeAll">销毁所有对象池,包括常驻对象池</param>
public void DestroyAll(bool includeAll)
{
if (includeAll)
{
foreach (var pool in _gameObjectPools)
{
pool.DestroyPool();
}
_gameObjectPools.Clear();
}
else
{
List<GameObjectPool> removeList = new List<GameObjectPool>();
foreach (var pool in _gameObjectPools)
{
if (pool.DontDestroy == false)
removeList.Add(pool);
}
foreach (var pool in removeList)
{
_gameObjectPools.Remove(pool);
pool.DestroyPool();
}
}
}
/// <summary>
/// 异步创建指定资源的游戏对象池
/// </summary>
/// <param name="location">资源定位地址</param>
/// <param name="dontDestroy">资源常驻不销毁</param>
/// <param name="initCapacity">对象池的初始容量</param>
/// <param name="maxCapacity">对象池的最大容量</param>
/// <param name="destroyTime">静默销毁时间(注意:小于零代表不主动销毁)</param>
public CreatePoolOperation CreateGameObjectPoolAsync(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
{
return CreateGameObjectPoolInternal(location, dontDestroy, initCapacity, maxCapacity, destroyTime);
}
/// <summary>
/// 同步创建指定资源的游戏对象池
/// </summary>
/// <param name="location">资源定位地址</param>
/// <param name="dontDestroy">资源常驻不销毁</param>
/// <param name="initCapacity">对象池的初始容量</param>
/// <param name="maxCapacity">对象池的最大容量</param>
/// <param name="destroyTime">静默销毁时间(注意:小于零代表不主动销毁)</param>
public CreatePoolOperation CreateGameObjectPoolSync(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
{
var operation = CreateGameObjectPoolInternal(location, dontDestroy, initCapacity, maxCapacity, destroyTime);
operation.WaitForAsyncComplete();
return operation;
}
/// <summary>
/// 创建指定资源的游戏对象池
/// </summary>
private CreatePoolOperation CreateGameObjectPoolInternal(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
{
if (maxCapacity < initCapacity)
throw new Exception("The max capacity value must be greater the init capacity value.");
GameObjectPool pool = TryGetGameObjectPool(location);
if (pool != null)
{
UniLogger.Warning($"GameObject pool is already existed : {location}");
var operation = new CreatePoolOperation(pool.AssetHandle);
YooAssets.StartOperation(operation);
return operation;
}
else
{
pool = new GameObjectPool(_spawnerRoot, location, dontDestroy, initCapacity, maxCapacity, destroyTime);
pool.CreatePool(_package);
_gameObjectPools.Add(pool);
var operation = new CreatePoolOperation(pool.AssetHandle);
YooAssets.StartOperation(operation);
return operation;
}
}
/// <summary>
/// 异步实例化一个游戏对象
/// </summary>
/// <param name="location">资源定位地址</param>
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
/// <param name="userDatas">用户自定义数据</param>
public SpawnHandle SpawnAsync(string location, bool forceClone = false, params System.Object[] userDatas)
{
return SpawnInternal(location, null, Vector3.zero, Quaternion.identity, forceClone, userDatas);
}
/// <summary>
/// 异步实例化一个游戏对象
/// </summary>
/// <param name="location">资源定位地址</param>
/// <param name="parent">父物体</param>
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
/// <param name="userDatas">用户自定义数据</param>
public SpawnHandle SpawnAsync(string location, Transform parent, bool forceClone = false, params System.Object[] userDatas)
{
return SpawnInternal(location, parent, Vector3.zero, Quaternion.identity, forceClone, userDatas);
}
/// <summary>
/// 异步实例化一个游戏对象
/// </summary>
/// <param name="location">资源定位地址</param>
/// <param name="parent">父物体</param>
/// <param name="position">世界坐标</param>
/// <param name="rotation">世界角度</param>
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
/// <param name="userDatas">用户自定义数据</param>
public SpawnHandle SpawnAsync(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone = false, params System.Object[] userDatas)
{
return SpawnInternal(location, parent, position, rotation, forceClone, userDatas);
}
/// <summary>
/// 同步实例化一个游戏对象
/// </summary>
/// <param name="location">资源定位地址</param>
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
/// <param name="userDatas">用户自定义数据</param>
public SpawnHandle SpawnSync(string location, bool forceClone = false, params System.Object[] userDatas)
{
SpawnHandle handle = SpawnInternal(location, null, Vector3.zero, Quaternion.identity, forceClone, userDatas);
handle.WaitForAsyncComplete();
return handle;
}
/// <summary>
/// 同步实例化一个游戏对象
/// </summary>
/// <param name="location">资源定位地址</param>
/// <param name="parent">父物体</param>
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
/// <param name="userDatas">用户自定义数据</param>
public SpawnHandle SpawnSync(string location, Transform parent, bool forceClone = false, params System.Object[] userDatas)
{
SpawnHandle handle = SpawnInternal(location, parent, Vector3.zero, Quaternion.identity, forceClone, userDatas);
handle.WaitForAsyncComplete();
return handle;
}
/// <summary>
/// 同步实例化一个游戏对象
/// </summary>
/// <param name="location">资源定位地址</param>
/// <param name="parent">父物体</param>
/// <param name="position">世界坐标</param>
/// <param name="rotation">世界角度</param>
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象</param>
/// <param name="userDatas">用户自定义数据</param>
public SpawnHandle SpawnSync(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone = false, params System.Object[] userDatas)
{
SpawnHandle handle = SpawnInternal(location, parent, position, rotation, forceClone, userDatas);
handle.WaitForAsyncComplete();
return handle;
}
/// <summary>
/// 实例化一个游戏对象
/// </summary>
private SpawnHandle SpawnInternal(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone, params System.Object[] userDatas)
{
var pool = TryGetGameObjectPool(location);
if (pool != null)
{
return pool.Spawn(parent, position, rotation, forceClone, userDatas);
}
// 如果不存在创建游戏对象池
pool = new GameObjectPool(_spawnerRoot, location, false, 0, int.MaxValue, -1f);
pool.CreatePool(_package);
_gameObjectPools.Add(pool);
return pool.Spawn(parent, position, rotation, forceClone, userDatas);
}
private GameObjectPool TryGetGameObjectPool(string location)
{
foreach (var pool in _gameObjectPools)
{
if (pool.Location == location)
return pool;
}
return null;
}
}
}

View File

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

View File

@@ -0,0 +1,21 @@
using System.Diagnostics;
namespace UniFramework.Pooling
{
internal static class UniLogger
{
[Conditional("DEBUG")]
public static void Log(string info)
{
UnityEngine.Debug.Log(info);
}
public static void Warning(string info)
{
UnityEngine.Debug.LogWarning(info);
}
public static void Error(string info)
{
UnityEngine.Debug.LogError(info);
}
}
}

View File

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

View File

@@ -0,0 +1,127 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
namespace UniFramework.Pooling
{
/// <summary>
/// 游戏对象池系统
/// </summary>
public static class UniPooling
{
private static bool _isInitialize = false;
private static GameObject _driver = null;
private static readonly List<Spawner> _spawners = new List<Spawner>();
/// <summary>
/// 初始化游戏对象池系统
/// </summary>
public static void Initalize()
{
if (_isInitialize)
throw new Exception($"{nameof(UniPooling)} is initialized !");
if (_isInitialize == false)
{
// 创建驱动器
_isInitialize = true;
_driver = new UnityEngine.GameObject($"[{nameof(UniPooling)}]");
_driver.AddComponent<UniPoolingDriver>();
UnityEngine.Object.DontDestroyOnLoad(_driver);
UniLogger.Log($"{nameof(UniPooling)} initalize !");
}
}
/// <summary>
/// 销毁游戏对象池系统
/// </summary>
public static void Destroy()
{
if (_isInitialize)
{
foreach (var spawner in _spawners)
{
spawner.Destroy();
}
_spawners.Clear();
_isInitialize = false;
if (_driver != null)
GameObject.Destroy(_driver);
UniLogger.Log($"{nameof(UniPooling)} destroy all !");
}
}
/// <summary>
/// 更新游戏对象池系统
/// </summary>
internal static void Update()
{
if (_isInitialize)
{
foreach (var spawner in _spawners)
{
spawner.Update();
}
}
}
/// <summary>
/// 创建游戏对象生成器
/// </summary>
/// <param name="packageName">资源包名称</param>
public static Spawner CreateSpawner(string packageName)
{
// 获取资源包
var assetPackage = YooAssets.GetPackage(packageName);
if (assetPackage == null)
throw new Exception($"Not found asset package : {packageName}");
// 检测资源包初始化状态
if (assetPackage.InitializeStatus == EOperationStatus.None)
throw new Exception($"Asset package {packageName} not initialize !");
if (assetPackage.InitializeStatus == EOperationStatus.Failed)
throw new Exception($"Asset package {packageName} initialize failed !");
if (HasSpawner(packageName))
return GetSpawner(packageName);
Spawner spawner = new Spawner(_driver, assetPackage);
_spawners.Add(spawner);
return spawner;
}
/// <summary>
/// 获取游戏对象生成器
/// </summary>
/// <param name="packageName">资源包名称</param>
public static Spawner GetSpawner(string packageName)
{
foreach (var spawner in _spawners)
{
if (spawner.PackageName == packageName)
return spawner;
}
UniLogger.Warning($"Not found spawner : {packageName}");
return null;
}
/// <summary>
/// 检测游戏对象生成器是否存在
/// </summary>
/// <param name="packageName">资源包名称</param>
public static bool HasSpawner(string packageName)
{
foreach (var spawner in _spawners)
{
if (spawner.PackageName == packageName)
return true;
}
return false;
}
}
}

View File

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

View File

@@ -0,0 +1,12 @@
using UnityEngine;
namespace UniFramework.Pooling
{
internal class UniPoolingDriver : MonoBehaviour
{
void Update()
{
UniPooling.Update();
}
}
}

View File

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

View File

@@ -0,0 +1,199 @@

namespace UniFramework.Utility
{
public sealed class UniTimer
{
/// <summary>
/// 延迟后,触发一次
/// </summary>
public static UniTimer CreateOnceTimer(float delay)
{
return new UniTimer(delay, -1, -1, 1);
}
/// <summary>
/// 延迟后,永久性的间隔触发
/// </summary>
/// <param name="delay">延迟时间</param>
/// <param name="interval">间隔时间</param>
public static UniTimer CreatePepeatTimer(float delay, float interval)
{
return new UniTimer(delay, interval, -1, -1);
}
/// <summary>
/// 延迟后,在一段时间内间隔触发
/// </summary>
/// <param name="delay">延迟时间</param>
/// <param name="interval">间隔时间</param>
/// <param name="duration">触发周期</param>
public static UniTimer CreatePepeatTimer(float delay, float interval, float duration)
{
return new UniTimer(delay, interval, duration, -1);
}
/// <summary>
/// 延迟后,间隔触发一定次数
/// </summary>
/// <param name="delay">延迟时间</param>
/// <param name="interval">间隔时间</param>
/// <param name="maxTriggerCount">最大触发次数</param>
public static UniTimer CreatePepeatTimer(float delay, float interval, long maxTriggerCount)
{
return new UniTimer(delay, interval, -1, maxTriggerCount);
}
/// <summary>
/// 延迟后,在一段时间内触发
/// </summary>
/// <param name="delay">延迟时间</param>
/// <param name="duration">触发周期</param>
public static UniTimer CreateDurationTimer(float delay, float duration)
{
return new UniTimer(delay, -1, duration, -1);
}
/// <summary>
/// 延迟后,永久触发
/// </summary>
public static UniTimer CreateForeverTimer(float delay)
{
return new UniTimer(delay, -1, -1, -1);
}
private readonly float _intervalTime;
private readonly float _durationTime;
private readonly long _maxTriggerCount;
// 需要重置的变量
private float _delayTimer = 0;
private float _durationTimer = 0;
private float _intervalTimer = 0;
private long _triggerCount = 0;
/// <summary>
/// 延迟时间
/// </summary>
public float DelayTime { private set; get; }
/// <summary>
/// 是否已经结束
/// </summary>
public bool IsOver { private set; get; }
/// <summary>
/// 是否已经暂停
/// </summary>
public bool IsPause { private set; get; }
/// <summary>
/// 延迟剩余时间
/// </summary>
public float Remaining
{
get
{
if (IsOver)
return 0f;
else
return System.Math.Max(0f, DelayTime - _delayTimer);
}
}
/// <summary>
/// 计时器
/// </summary>
/// <param name="delay">延迟时间</param>
/// <param name="interval">间隔时间</param>
/// <param name="duration">运行时间</param>
/// <param name="maxTriggerTimes">最大触发次数</param>
public UniTimer(float delay, float interval, float duration, long maxTriggerCount)
{
DelayTime = delay;
_intervalTime = interval;
_durationTime = duration;
_maxTriggerCount = maxTriggerCount;
}
/// <summary>
/// 暂停计时器
/// </summary>
public void Pause()
{
IsPause = true;
}
/// <summary>
/// 恢复计时器
/// </summary>
public void Resume()
{
IsPause = false;
}
/// <summary>
/// 结束计时器
/// </summary>
public void Kill()
{
IsOver = true;
}
/// <summary>
/// 重置计时器
/// </summary>
public void Reset()
{
_delayTimer = 0;
_durationTimer = 0;
_intervalTimer = 0;
_triggerCount = 0;
IsOver = false;
IsPause = false;
}
/// <summary>
/// 更新计时器
/// </summary>
public bool Update(float deltaTime)
{
if (IsOver || IsPause)
return false;
_delayTimer += deltaTime;
if (_delayTimer < DelayTime)
return false;
if(_intervalTime > 0)
_intervalTimer += deltaTime;
if (_durationTime > 0)
_durationTimer += deltaTime;
// 检测间隔执行
if (_intervalTime > 0)
{
if (_intervalTimer < _intervalTime)
return false;
_intervalTimer = 0;
}
// 检测结束条件
if (_durationTime > 0)
{
if (_durationTimer >= _durationTime)
Kill();
}
// 检测结束条件
if (_maxTriggerCount > 0)
{
_triggerCount++;
if (_triggerCount >= _maxTriggerCount)
Kill();
}
return true;
}
}
}

View File

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

View File

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

View File

@@ -1,3 +1,5 @@
using System.Collections;
using Cysharp.Threading.Tasks;
using GameBase;
using TEngine;
@@ -28,7 +30,15 @@ public partial class GameApp:Singleton<GameApp>
/// </summary>
private void StartGameLogic()
{
StartBattleRoom().Forget();
}
private async UniTaskVoid StartBattleRoom()
{
await GameModule.Resource.LoadSceneAsync("scene_battle").ToUniTask(Utility.Unity.Behaviour);
BattleRoom battleRoom = new BattleRoom();
await battleRoom.LoadRoom().ToUniTask(Utility.Unity.Behaviour);
}
/// <summary>

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using TEngine;
using UniFramework.Pooling;
public partial class GameApp
{
@@ -17,7 +18,8 @@ public partial class GameApp
/// </summary>
private void InitSystemSetting()
{
// 初始化对象池系统
UniPooling.Initalize();
}
/// <summary>