范川铭

1.删除不需要得文件

... ... @@ -51,17 +51,14 @@
<Compile Include="Assets\Scripts\UI\Test3.cs" />
<Compile Include="Assets\Scripts\Common\Singleton.cs" />
<Compile Include="Assets\Scripts\Manager\UIManager.cs" />
<Compile Include="Assets\Scripts\ScrollView\ItemUI.cs" />
<Compile Include="Assets\Scripts\UI\Test2.cs" />
<Compile Include="Assets\Scripts\UI\ItemTest.cs" />
<Compile Include="Assets\Scripts\Common\UIBase.cs" />
<Compile Include="Assets\Scripts\Main.cs" />
<Compile Include="Assets\Scripts\UI\ItemTestPanel.cs" />
<Compile Include="Assets\Scripts\UI\Test1.cs" />
<Compile Include="Assets\Scripts\ScrollView\CustomListComponent.cs" />
<Compile Include="Assets\Scripts\Common\TimeControl.cs" />
<Compile Include="Assets\Scripts\Manager\ResourcesManager.cs" />
<Compile Include="Assets\Scripts\ScrollViewTest.cs" />
<Compile Include="Assets\Scripts\Manager\AudioManager.cs" />
<Compile Include="Assets\Scripts\UI\TimeTest.cs" />
<Compile Include="Assets\Scripts\Manager\UIAnimation.cs" />
... ...
... ... @@ -3,7 +3,7 @@ using UnityEngine;
using UnityEngine.EventSystems;
public abstract class BaseItem<T> : MonoBehaviour, IPointerClickHandler where T : struct
public abstract class BaseItem<T> : MonoBehaviour, IPointerClickHandler where T : struct
{
/// <summary>
/// Item保存得数据
... ... @@ -31,7 +31,7 @@ public abstract class BaseItem<T> : MonoBehaviour, IPointerClickHandler where T
/// </summary>
/// <param name="data"></param>
public void SetupData(T data)
{
{
itemData = data;
UpdateItem();
}
... ...
using UnityEngine;
using System.Collections.Generic;
public enum ScrollDirection
{
Horizontal,
Vertical
}
public enum LoopMode
{
Normal,
InfiniteLoop
}
public enum SnapMode
{
Free,
CenterAligned
}
public enum DragMode
{
FixedDistance,
MouseDistance
}
public enum EasingType
{
Linear,
EaseIn,
EaseOut,
EaseInOut
}
public class CustomListComponent : MonoBehaviour
{
[Header("基本设置")] [SerializeField] private ScrollDirection direction = ScrollDirection.Horizontal;
[SerializeField] private LoopMode loopMode = LoopMode.InfiniteLoop;
[SerializeField] private SnapMode snapMode = SnapMode.CenterAligned;
[SerializeField] private DragMode dragMode = DragMode.MouseDistance;
[SerializeField] private EasingType easingType = EasingType.EaseOut;
[Header("Item设置")] [SerializeField] private GameObject itemPrefab;
[SerializeField] private float itemSize = 100f;
[SerializeField] private float spacing = 20f;
[Header("动画设置")] [SerializeField] private float snapSpeed = 5f;
[SerializeField] private float dragSensitivity = 1f;
[SerializeField] private float fixedDragDistance = 50f;
[Header("数据")] [SerializeField] private List<ItemData> itemDataList = new List<ItemData>();
private RectTransform rectTransform;
private List<ItemInstance> activeItems = new List<ItemInstance>();
private float viewportSize;
private int maxVisibleItems;
private float totalContentSize;
private float currentPosition;
private float targetPosition;
private Vector2 lastMousePosition;
private bool isDragging;
private int centerItemIndex;
private float dragStartTime;
private float dragStartPosition;
[System.Serializable]
public class ItemData
{
public string id;
public string name;
public Sprite icon;
public object data;
}
private class ItemInstance
{
public GameObject gameObject;
public RectTransform rectTransform;
public int dataIndex;
public ItemUI itemUI;
}
public delegate void CenterItemChangedHandler(int index, ItemData data);
public event CenterItemChangedHandler OnCenterItemChanged;
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
CalculateViewportSize();
CalculateMaxVisibleItems();
InitializeItems();
}
private void CalculateViewportSize()
{
if (direction == ScrollDirection.Horizontal)
{
viewportSize = rectTransform.rect.width;
}
else
{
viewportSize = rectTransform.rect.height;
}
}
private void CalculateMaxVisibleItems()
{
// 计算最多需要多少个Item才能铺满视口
maxVisibleItems = Mathf.CeilToInt((viewportSize + spacing) / (itemSize + spacing)) + 2;
Debug.Log($"最多可见Item数量: {maxVisibleItems}");
}
private void InitializeItems()
{
// 清除现有Item
foreach (var item in activeItems)
{
Destroy(item.gameObject);
}
activeItems.Clear();
// 创建必要的Item实例
for (int i = 0; i < maxVisibleItems; i++)
{
GameObject itemGO = Instantiate(itemPrefab, transform);
ItemInstance item = new ItemInstance
{
gameObject = itemGO,
rectTransform = itemGO.GetComponent<RectTransform>(),
dataIndex = i % itemDataList.Count,
itemUI = itemGO.GetComponent<ItemUI>()
};
UpdateItemPosition(item, i);
UpdateItemData(item);
activeItems.Add(item);
}
// 计算总内容大小
totalContentSize = itemDataList.Count * (itemSize + spacing) - spacing;
// 初始化位置
currentPosition = 0;
targetPosition = 0;
UpdateCenterItem();
}
private void UpdateItemPosition(ItemInstance item, int index)
{
float position = index * (itemSize + spacing);
if (direction == ScrollDirection.Horizontal)
{
item.rectTransform.anchoredPosition = new Vector2(position - currentPosition, 0);
}
else
{
item.rectTransform.anchoredPosition = new Vector2(0, -(position - currentPosition));
}
}
private void UpdateItemData(ItemInstance item)
{
if (item.itemUI != null && item.dataIndex < itemDataList.Count)
{
item.itemUI.SetData(itemDataList[item.dataIndex]);
}
}
private void Update()
{
HandleInput();
UpdateScrollPosition();
UpdateItems();
}
private void HandleInput()
{
if (Input.GetMouseButtonDown(0))
{
if (RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Input.mousePosition))
{
isDragging = true;
lastMousePosition = Input.mousePosition;
dragStartTime = Time.time;
dragStartPosition = currentPosition;
}
}
if (Input.GetMouseButtonUp(0))
{
if (isDragging)
{
isDragging = false;
if (snapMode == SnapMode.CenterAligned)
{
SnapToNearestItem();
}
}
}
if (isDragging)
{
Vector2 mouseDelta = Input.mousePosition - new Vector3(lastMousePosition.x, lastMousePosition.y, 0);
lastMousePosition = Input.mousePosition;
float dragAmount = direction == ScrollDirection.Horizontal ? mouseDelta.x : -mouseDelta.y;
if (dragMode == DragMode.FixedDistance)
{
dragAmount = Mathf.Sign(dragAmount) * fixedDragDistance;
}
currentPosition -= dragAmount * dragSensitivity;
// 处理边界
if (loopMode == LoopMode.Normal)
{
currentPosition = Mathf.Clamp(currentPosition, 0, Mathf.Max(0, totalContentSize - viewportSize));
}
}
}
private void UpdateScrollPosition()
{
if (!isDragging && currentPosition != targetPosition)
{
float deltaTime = Time.deltaTime * snapSpeed;
// 应用缓动函数
switch (easingType)
{
case EasingType.Linear:
currentPosition = Mathf.Lerp(currentPosition, targetPosition, deltaTime);
break;
case EasingType.EaseIn:
currentPosition = EaseIn(currentPosition, targetPosition, deltaTime);
break;
case EasingType.EaseOut:
currentPosition = EaseOut(currentPosition, targetPosition, deltaTime);
break;
case EasingType.EaseInOut:
currentPosition = EaseInOut(currentPosition, targetPosition, deltaTime);
break;
}
if (Mathf.Abs(currentPosition - targetPosition) < 0.1f)
{
currentPosition = targetPosition;
}
}
}
private void UpdateItems()
{
if (loopMode == LoopMode.InfiniteLoop)
{
// 处理无限循环
foreach (var item in activeItems)
{
bool needsUpdate = false;
if (direction == ScrollDirection.Horizontal)
{
float itemPos = item.rectTransform.anchoredPosition.x + currentPosition;
// 如果Item超出左边界,移动到右侧
if (itemPos < -itemSize)
{
item.dataIndex = (item.dataIndex + activeItems.Count) % itemDataList.Count;
needsUpdate = true;
}
// 如果Item超出右边界,移动到左侧
else if (itemPos > viewportSize)
{
item.dataIndex = (item.dataIndex - activeItems.Count + itemDataList.Count) % itemDataList.Count;
needsUpdate = true;
}
}
else
{
float itemPos = -(item.rectTransform.anchoredPosition.y - currentPosition);
// 如果Item超出上边界,移动到下侧
if (itemPos < -itemSize)
{
item.dataIndex = (item.dataIndex + activeItems.Count) % itemDataList.Count;
needsUpdate = true;
}
// 如果Item超出下边界,移动到上侧
else if (itemPos > viewportSize)
{
item.dataIndex = (item.dataIndex - activeItems.Count + itemDataList.Count) % itemDataList.Count;
needsUpdate = true;
}
}
if (needsUpdate)
{
UpdateItemData(item);
// 重新计算位置
int virtualIndex = Mathf.FloorToInt(currentPosition / (itemSize + spacing));
virtualIndex = (virtualIndex + item.dataIndex) % itemDataList.Count;
UpdateItemPosition(item, virtualIndex);
}
else
{
// 仅更新位置
UpdateItemPosition(item,
Mathf.FloorToInt((item.rectTransform.anchoredPosition.x + currentPosition) /
(itemSize + spacing)));
}
}
}
UpdateCenterItem();
}
private void SnapToNearestItem()
{
if (itemDataList.Count == 0) return;
// 计算最接近中心的Item
float centerPos = viewportSize / 2;
float closestDistance = float.MaxValue;
int closestIndex = 0;
foreach (var item in activeItems)
{
float itemPos = direction == ScrollDirection.Horizontal
? item.rectTransform.anchoredPosition.x + itemSize / 2
: -(item.rectTransform.anchoredPosition.y - itemSize / 2);
float distance = Mathf.Abs(itemPos - centerPos);
if (distance < closestDistance)
{
closestDistance = distance;
closestIndex = item.dataIndex;
}
}
// 设置目标位置
float targetPos = closestIndex * (itemSize + spacing);
// 调整目标位置使选中的Item居中
if (direction == ScrollDirection.Horizontal)
{
targetPos -= (viewportSize - itemSize) / 2;
}
else
{
targetPos -= (viewportSize - itemSize) / 2;
}
// 限制在边界内
if (loopMode == LoopMode.Normal)
{
targetPos = Mathf.Clamp(targetPos, 0, Mathf.Max(0, totalContentSize - viewportSize));
}
targetPosition = targetPos;
}
private void UpdateCenterItem()
{
float centerPos = viewportSize / 2;
float closestDistance = float.MaxValue;
int newCenterIndex = -1;
foreach (var item in activeItems)
{
float itemPos = direction == ScrollDirection.Horizontal
? item.rectTransform.anchoredPosition.x + itemSize / 2
: -(item.rectTransform.anchoredPosition.y - itemSize / 2);
float distance = Mathf.Abs(itemPos - centerPos);
if (distance < closestDistance)
{
closestDistance = distance;
newCenterIndex = item.dataIndex;
}
}
if (newCenterIndex != centerItemIndex && newCenterIndex >= 0 && newCenterIndex < itemDataList.Count)
{
centerItemIndex = newCenterIndex;
OnCenterItemChanged?.Invoke(centerItemIndex, itemDataList[centerItemIndex]);
}
}
// 缓动函数
private float EaseIn(float start, float end, float value)
{
end -= start;
return end * Mathf.Pow(value, 2) + start;
}
private float EaseOut(float start, float end, float value)
{
end -= start;
return -end * value * (value - 2) + start;
}
private float EaseInOut(float start, float end, float value)
{
value /= 0.5f;
end -= start;
if (value < 1)
{
return end * 0.5f * Mathf.Pow(value, 2) + start;
}
value--;
return -end * 0.5f * (value * (value - 2) - 1) + start;
}
// 公共方法
public void SetDirection(ScrollDirection newDirection)
{
direction = newDirection;
CalculateViewportSize();
InitializeItems();
}
public void SetLoopMode(LoopMode newMode)
{
loopMode = newMode;
}
public void SetSnapMode(SnapMode newMode)
{
snapMode = newMode;
}
public void SetDragMode(DragMode newMode)
{
dragMode = newMode;
}
public void SetEasingType(EasingType newType)
{
easingType = newType;
}
public void SetItemSize(float size)
{
itemSize = size;
CalculateMaxVisibleItems();
InitializeItems();
}
public void SetSpacing(float newSpacing)
{
spacing = newSpacing;
CalculateMaxVisibleItems();
InitializeItems();
}
public void SetItemData(List<ItemData> dataList)
{
itemDataList = dataList;
CalculateMaxVisibleItems();
InitializeItems();
}
public ItemData GetCenterItemData()
{
if (centerItemIndex >= 0 && centerItemIndex < itemDataList.Count)
{
return itemDataList[centerItemIndex];
}
return null;
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 50f895cd92be3cb43969984721391f5f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using UnityEngine.UI;
public class ItemUI : MonoBehaviour
{
[SerializeField] private Text nameText;
[SerializeField] private Image iconImage;
public void SetData(CustomListComponent.ItemData data)
{
if (nameText != null)
{
nameText.text = data.name;
}
if (iconImage != null && data.icon != null)
{
iconImage.sprite = data.icon;
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 1d73e51513498ae43b0936409f2de324
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScrollViewTest : MonoBehaviour
{
public CustomListComponent myScrollView;
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 2f21380e731302746b81972d69d9b121
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
... ... @@ -8,7 +8,7 @@ MonoBehaviour:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 1
m_EditorHideFlags: 0
m_Script: {fileID: 12004, guid: 0000000000000000e000000000000000, type: 0}
m_Name:
m_EditorClassIdentifier:
... ... @@ -19,7 +19,7 @@ MonoBehaviour:
width: 2560
height: 1357.3334
m_ShowMode: 4
m_Title: Console
m_Title: Hierarchy
m_RootView: {fileID: 2}
m_MinSize: {x: 875, y: 300}
m_MaxSize: {x: 10000, y: 10000}
... ... @@ -120,7 +120,7 @@ MonoBehaviour:
m_MinSize: {x: 300, y: 100}
m_MaxSize: {x: 24288, y: 16192}
vertical: 0
controlID: 81
controlID: 244
draggingID: 0
--- !u!114 &6
MonoBehaviour:
... ... @@ -146,7 +146,7 @@ MonoBehaviour:
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 8096, y: 16192}
vertical: 1
controlID: 17
controlID: 132
draggingID: 0
--- !u!114 &7
MonoBehaviour:
... ... @@ -158,7 +158,7 @@ MonoBehaviour:
m_Enabled: 1
m_EditorHideFlags: 1
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
m_Name: GameView
m_Name: AssetStoreWindow
m_EditorClassIdentifier:
m_Children: []
m_Position:
... ... @@ -167,15 +167,15 @@ MonoBehaviour:
y: 0
width: 1292
height: 682
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 4000, y: 4000}
m_ActualView: {fileID: 15}
m_MinSize: {x: 456, y: 375}
m_MaxSize: {x: 4001, y: 4021}
m_ActualView: {fileID: 13}
m_Panes:
- {fileID: 14}
- {fileID: 15}
- {fileID: 13}
m_Selected: 1
m_LastSelected: 0
m_Selected: 2
m_LastSelected: 1
--- !u!114 &8
MonoBehaviour:
m_ObjectHideFlags: 52
... ... @@ -226,7 +226,7 @@ MonoBehaviour:
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 8096, y: 16192}
vertical: 1
controlID: 82
controlID: 191
draggingID: 0
--- !u!114 &10
MonoBehaviour:
... ... @@ -247,8 +247,8 @@ MonoBehaviour:
y: 0
width: 384
height: 751.3333
m_MinSize: {x: 200, y: 200}
m_MaxSize: {x: 4000, y: 4000}
m_MinSize: {x: 202, y: 221}
m_MaxSize: {x: 4002, y: 4021}
m_ActualView: {fileID: 17}
m_Panes:
- {fileID: 17}
... ... @@ -299,8 +299,8 @@ MonoBehaviour:
y: 0
width: 884
height: 1307.3334
m_MinSize: {x: 275, y: 50}
m_MaxSize: {x: 4000, y: 4000}
m_MinSize: {x: 276, y: 71}
m_MaxSize: {x: 4001, y: 4021}
m_ActualView: {fileID: 19}
m_Panes:
- {fileID: 19}
... ... @@ -329,7 +329,7 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 72.66667
width: 1168.3334
width: 1291
height: 661
m_SerializedDataModeController:
m_DataMode: 0
... ... @@ -405,7 +405,7 @@ MonoBehaviour:
floating: 0
collapsed: 0
displayed: 1
snapOffset: {x: 0, y: 0}
snapOffset: {x: 0, y: 24.666666}
snapOffsetDelta: {x: 0, y: 0}
snapCorner: 0
id: unity-scene-view-toolbar
... ... @@ -749,9 +749,9 @@ MonoBehaviour:
m_PlayAudio: 0
m_AudioPlay: 0
m_Position:
m_Target: {x: 1301.7489, y: 431.4366, z: 3.0009701}
m_Target: {x: 784.90393, y: 472.3755, z: -1.2112993}
speed: 2
m_Value: {x: 1301.7489, y: 431.4366, z: 3.0009701}
m_Value: {x: 961.04877, y: 479.5093, z: -0.20217133}
m_RenderMode: 0
m_CameraMode:
drawMode: 0
... ... @@ -799,11 +799,11 @@ MonoBehaviour:
m_Rotation:
m_Target: {x: -0.0071905754, y: -0.0035052756, z: -0.000025474808, w: 0.9999826}
speed: 2
m_Value: {x: -0.0071904706, y: -0.0035052246, z: -0.000025474437, w: 0.99996805}
m_Value: {x: 0.015107922, y: 0.982547, z: 0.16077192, w: -0.09233392}
m_Size:
m_Target: 261.93716
m_Target: 201.43204
speed: 2
m_Value: 261.93716
m_Value: 35.840363
m_Ortho:
m_Target: 0
speed: 2
... ... @@ -997,9 +997,9 @@ MonoBehaviour:
m_SceneHierarchy:
m_TreeViewState:
scrollPos: {x: 0, y: 0}
m_SelectedIDs: b6f7ffff
m_LastClickedID: -2122
m_ExpandedIDs: b6f7ffff64f8ffff12f9ffff2cfbffff
m_SelectedIDs:
m_LastClickedID: 0
m_ExpandedIDs: 10e5feff8054ffff3479ffff9e6f0000
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
... ... @@ -1067,7 +1067,8 @@ MonoBehaviour:
m_ShowAllHits: 0
m_SkipHidden: 0
m_SearchArea: 1
m_Folders: []
m_Folders:
- Assets/resources/Prefab
m_Globs: []
m_OriginalText:
m_ImportLogFlags: 0
... ... @@ -1083,7 +1084,7 @@ MonoBehaviour:
scrollPos: {x: 0, y: 0}
m_SelectedIDs: fe390000
m_LastClickedID: 14846
m_ExpandedIDs: 00000000c85a00006a5b00006c5b00006e5b0000705b0000
m_ExpandedIDs: 000000005e6f000000ca9a3b
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
... ... @@ -1111,7 +1112,7 @@ MonoBehaviour:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
m_LastClickedID: 0
m_ExpandedIDs: ffffffff00000000c85a00006a5b00006c5b00006e5b0000705b0000a25b0000a45b0000a65b0000ac5b0000be5b0000
m_ExpandedIDs: 9a42ffffffffffff000000005e6f000000ca9a3b
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
... ...