Files
aibis-dream/Assets/Scripts/SubWay/ParallaxManager.cs
T
2024-11-28 14:20:06 +08:00

202 lines
7.0 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
[System.Serializable]
public class ParallaxLayerConfig
{
public GameObject layer; // 背景层的游戏对象
public float scrollSpeed; // 每层的滚动速度
public float scrollOffset; // 每层的滚动偏移量
}
public class ParallaxManager : MonoBehaviour
{
public ParallaxLayerConfig[] layerConfigs; // 背景层配置数组
public ParallaxObjectCategoryConfig[] categoryConfigs; // 多种物体配置类别
public float speedMultiplier = 1; // 加速系数
private Dictionary<string, List<GameObject>> objectPools = new Dictionary<string, List<GameObject>>(); // 物体池
void Start()
{
// 初始化背景层滚动
foreach (var config in layerConfigs)
{
StartLayerScroll(config);
}
// 初始化物体池并启动物体生成逻辑
foreach (var category in categoryConfigs)
{
InitializeObjectPool(category);
if (category.useIntervalGeneration)
{
StartCoroutine(ManageObjectGeneration(category));
}
else
{
// 按照距离生成
StartCoroutine(ManageObjectGenerationByDistance(category));
}
// category.SpawnObjects(this); // 启动物体生成
}
}
// 初始化物体池
private void InitializeObjectPool(ParallaxObjectCategoryConfig categoryConfig)
{
List<GameObject> pool = new List<GameObject>();
for (int i = 0; i < categoryConfig.objects.Length; i++)
{
GameObject prefab = categoryConfig.objects[i];
GameObject obj = Instantiate(prefab, prefab.transform.position, Quaternion.identity, transform);
obj.SetActive(false);
pool.Add(obj);
}
objectPools[categoryConfig.categoryName] = pool;
Debug.Log($"为分类 {categoryConfig.categoryName} 初始化池子,池中物体数:{pool.Count}");
}
// 开始背景层滚动
private void StartLayerScroll(ParallaxLayerConfig config)
{
Vector3 startPosition = config.layer.transform.position;
float endPositionX = startPosition.x - config.scrollOffset;
config.layer.transform.DOLocalMoveX(endPositionX, config.scrollSpeed * speedMultiplier)
.SetEase(Ease.Linear)
.OnKill(() => ResetLayerPosition(config));
}
// 重置背景层位置
private void ResetLayerPosition(ParallaxLayerConfig config)
{
Vector3 currentPosition = config.layer.transform.position;
config.layer.transform.position = new Vector3(currentPosition.x + config.scrollOffset * 2, currentPosition.y, currentPosition.z);
StartLayerScroll(config);
}
// 管理物体生成(基于距离)
public IEnumerator ManageObjectGenerationByDistance(ParallaxObjectCategoryConfig categoryConfig)
{
var pool = objectPools[categoryConfig.categoryName];
GameObject firstObject = pool[0];
if (!firstObject.activeInHierarchy)
{
firstObject.transform.position = categoryConfig.objects[0].transform.position;
firstObject.SetActive(true);
StartObjectMoveAnimation(firstObject, categoryConfig);
Debug.Log($"生成了第一个物体: {firstObject.name}, 位置: {firstObject.transform.position}");
}
GameObject lastObject = firstObject;
//GameObject lastObject = null;
while (true)
{
// 检查是否需要生成新物体
if (lastObject == null || lastObject.transform.position.x < categoryConfig.generationThreshold)
{
GameObject obj = GetInactiveObjectFromPool(categoryConfig.categoryName);
if (obj != null)
{
SpawnObject(obj, categoryConfig);
lastObject = obj;
}
}
yield return null;
}
}
// 管理物体生成:按时间间隔生成
public IEnumerator ManageObjectGeneration(ParallaxObjectCategoryConfig categoryConfig)
{
if (!objectPools.ContainsKey(categoryConfig.categoryName))
{
Debug.LogError($"没有为分类 {categoryConfig.categoryName} 初始化对象池!");
yield break;
}
var pool = objectPools[categoryConfig.categoryName];
// // 初始化生成第一个物体
// GameObject firstObject = pool.Find(o => !o.activeInHierarchy);
// if (firstObject != null)
// {
// firstObject.SetActive(true);
// StartObjectMoveAnimation(firstObject, categoryConfig);
// //SpawnObject(firstObject, categoryConfig);
// Debug.Log($"初始生成物体: {firstObject.name}, 位置: {firstObject.transform.position}");
// }
// else
// {
// Debug.LogWarning($"对象池 {categoryConfig.categoryName} 没有可用的初始物体!");
// }
// 持续生成物体
while (true)
{
yield return new WaitForSeconds(categoryConfig.spawnInterval);
// 从池中查找未激活的对象
// GameObject obj = pool.Find(o => !o.activeInHierarchy);
GameObject obj = GetInactiveObjectFromPool(categoryConfig.categoryName);
if (obj != null)
{
SpawnObject(obj, categoryConfig);
Debug.Log($"生成物体: {obj.name}, 当前池大小: {pool.Count}");
}
else
{
Debug.LogWarning($"对象池 {categoryConfig.categoryName} 中没有可用物体!可能需要增加池中物体数量。");
}
}
}
// 获取池中未激活的物体
private GameObject GetInactiveObjectFromPool(string categoryName)
{
if (objectPools.TryGetValue(categoryName, out var pool))
{
// 筛选出所有未激活的对象
var inactiveObjects = pool.FindAll(o => !o.activeInHierarchy);
if (inactiveObjects.Count > 0)
{
// 从未激活的对象中随机选择一个
return inactiveObjects[Random.Range(0, inactiveObjects.Count)];
}
}
return null; // 如果没有未激活的对象
}
// 生成物体逻辑
private void SpawnObject(GameObject obj, ParallaxObjectCategoryConfig categoryConfig)
{
float xStart = categoryConfig.xSpawnRange;
//float yStart = obj.objects; // 可配置的随机高度范围
obj.transform.position = new Vector3(xStart, obj.transform.position.y, obj.transform.position.z);
obj.SetActive(true);
StartObjectMoveAnimation(obj, categoryConfig);
}
// 启动物体移动动画
private void StartObjectMoveAnimation(GameObject obj, ParallaxObjectCategoryConfig config)
{
float endX = -config.xSpawnRange;
obj.transform.DOMoveX(endX, config.speed * speedMultiplier)
.SetEase(Ease.Linear)
.OnKill(() =>
{
obj.SetActive(false);
Debug.Log($"物体 {obj.name} 动画结束,回收到池中");
});
}
}