This commit is contained in:
wuwenbo 2025-05-28 16:58:08 +08:00
commit 3ec9b8fc41
17 changed files with 10758 additions and 6666 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -146,7 +146,6 @@ GameObject:
- component: {fileID: 4883393105480666559}
- component: {fileID: 2617663671298611723}
- component: {fileID: 2053365445280533371}
- component: {fileID: 8219649181624787370}
m_Layer: 5
m_Name: Button
m_TagString: Untagged
@ -231,50 +230,6 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &8219649181624787370
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1538021311469209037}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 1, g: 0, b: 0.836318, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 2053365445280533371}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &2184308004123956235
GameObject:
m_ObjectHideFlags: 0
@ -458,6 +413,7 @@ GameObject:
- component: {fileID: 6708111836739851584}
- component: {fileID: 7382933239381170671}
- component: {fileID: 3698834877823843345}
- component: {fileID: 1499514374725069982}
m_Layer: 5
m_Name: MainUIButton
m_TagString: Untagged
@ -531,7 +487,51 @@ MonoBehaviour:
m_EditorClassIdentifier:
popupClip: {fileID: 0}
popinClip: {fileID: 0}
normalColor: {r: 1, g: 1, b: 1, a: 1}
highlightColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1}
normalColor: {r: 0.42745098, g: 0.6784314, b: 0, a: 0.8745098}
highlightColor: {r: 1, g: 0, b: 0.6250315, a: 0.8980392}
LockedColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
IsLocked: 0
--- !u!114 &1499514374725069982
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7763630946422454447}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 0
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 0}
m_OnClick:
m_PersistentCalls:
m_Calls: []

File diff suppressed because it is too large Load Diff

View File

@ -30,9 +30,6 @@ namespace Logic
public bool DebugShowAIID = false;
[Header("Play Settings")]
public uint width;
public uint height;
public uint playerCount;
public int cityCount;
public int unitCount;
public int turn;
@ -118,7 +115,7 @@ namespace Logic
//移动镜头+显示开局提示
//UIManager.CenterMessageUI.SetCenterMessageShow(UICenterMessageID.StartGame,MapData.PlayerMap.SelfPlayerData);
}
public void StartGame(uint h, uint w, uint civId, uint forceId)
public void StartGame(uint h, uint w,uint playerCount, uint civId, uint forceId)
{
MapConfig = new MapConfig(h,w,playerCount,civId,forceId);
//初始化所有Data

View File

@ -38,7 +38,7 @@ public class ChooseUI
() => { NeedShow = false;
_main.UIManager.GameUI.MainUI.NeedShow = true;
});
ROChooseUI.transform.Find("ForceListPanel/ModeButton/StartButton").GetComponent<Button>().onClick.AddListener(
ROChooseUI.transform.Find("ForceListPanel/ModeButton/StartButton/Button").GetComponent<Button>().onClick.AddListener(
() =>
{
StartGame();
@ -49,7 +49,7 @@ public class ChooseUI
public void Init()
{
for (int i = 0; i < 4; i++)
for (int i = 0; i < 3; i++)
{
int index = i; // 闭包用局部变量
int row = i / 3;
@ -59,20 +59,41 @@ public class ChooseUI
fadeIns[i] = Resources.Load<AnimationClip>($"Animations/UI/ChooseUI{_name[i]}PanelFadeIn");
fadeOuts[i] = Resources.Load<AnimationClip>($"Animations/UI/ChooseUI{_name[i]}PanelFadeOut");
_buttons[i].onClick.AddListener(() => SwitchToPanel(index));
if(!ROChooseUI.transform.Find($"ForceListPanel/TribeList/{_name[i]}Div").GetComponent<TribeHoverEffect>().IsLocked)
_buttons[i].onClick.AddListener(() => SwitchToPanel(index));
}
}
public void StartGame()
{
if (_currentPanelIndex == -1)
return;
NeedShow = false;
uint civ = _civ[_currentPanelIndex];
string mapSizeS = ROChooseUI.transform.Find("ForceListPanel/SettingBar/MapSize").GetComponent<ToggleButtonGroupController>()
.GetSelectedButtonName();
string playerCountS = ROChooseUI.transform.Find("ForceListPanel/SettingBar/EnemyCount").GetComponent<ToggleButtonGroupController>()
.GetSelectedButtonName();
string diffS = ROChooseUI.transform.Find("ForceListPanel/SettingBar/Difficulty").GetComponent<ToggleButtonGroupController>()
.GetSelectedButtonName();
if (!int.TryParse(mapSizeS.Substring(10), out int mapSize))
mapSize = 18;
if (!int.TryParse(playerCountS.Substring(12), out int playerCount))
playerCount = 18;
NeedShow = false;
_currentPanelIndex = 0;
for (int i = 0; i < 3; i++)
{
if (!ROChooseUI.transform.Find($"ForceListPanel/TribeList/{_name[i]}Div").GetComponent<TribeHoverEffect>()
.CheckIsSelected())
continue;
_currentPanelIndex = i;
break;
}
uint civ = _civ[_currentPanelIndex];
uint force = _force[_currentPanelIndex];
_main.StartGame(15, 15, civ, force);
_main.StartGame((uint)mapSize, (uint)mapSize,(uint)playerCount, civ, force);
}
public void Update()

View File

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

View File

@ -0,0 +1,61 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
public class ToggleButtonGroupController : MonoBehaviour
{
public string buttonGroupName = "ButtonGroup";
private Transform buttonGroup;
private List<Button> buttons = new List<Button>();
private Button selectedButton;
// 高亮与默认颜色
private readonly Color selectedColor = new Color32(0x3E, 0xAB, 0x02, 255); // #3EAB02
private readonly Color normalColor = new Color32(0x00, 0x00, 0x00, 112); // #000000, alpha 112
void Start()
{
buttonGroup = transform.Find(buttonGroupName);
if (buttonGroup == null)
{
Debug.LogError($"ButtonGroup '{buttonGroupName}' not found under {gameObject.name}");
return;
}
// 查找所有按钮并绑定点击事件
foreach (Transform child in buttonGroup)
{
Button btn = child.GetComponent<Button>();
if (btn != null)
{
buttons.Add(btn);
btn.onClick.AddListener(() => OnButtonClicked(btn));
}
}
// 默认选中第一个
if (buttons.Count > 0)
OnButtonClicked(buttons[0]);
}
private void OnButtonClicked(Button clickedButton)
{
selectedButton = clickedButton;
foreach (Button btn in buttons)
{
Image bgImage = btn.transform.Find("BG")?.GetComponent<Image>();
if (bgImage != null)
{
bgImage.color = (btn == selectedButton) ? selectedColor : normalColor;
}
}
}
public string GetSelectedButtonName()
{
return selectedButton != null ? selectedButton.name : "";
}
}

View File

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

View File

@ -0,0 +1,47 @@
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace UI.Common{
[RequireComponent(typeof(Image))]
public class ChooseUIButtonHoverColor : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
private Image parentImage;
private Color normalColor = new Color32(0x54, 0xC1, 0x4F, 255); // #54C14F
private Color hoverColor = new Color32(0x20, 0x86, 0x1C, 255); // #20861C
void Start()
{
// 找到父对象 StartButton 上的 Image
var parent = transform.parent;
if (parent != null)
{
parentImage = parent.GetComponent<Image>();
}
if (parentImage != null)
{
parentImage.color = normalColor;
}
else
{
Debug.LogError($"{name}: 找不到父对象 Image 组件!");
}
}
public void OnPointerEnter(PointerEventData eventData)
{
if (parentImage != null)
parentImage.color = hoverColor;
}
public void OnPointerExit(PointerEventData eventData)
{
if (parentImage != null)
parentImage.color = normalColor;
}
}
}

View File

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

View File

@ -0,0 +1,122 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
namespace UI.Common
{
[RequireComponent(typeof(ScrollRect))]
public class ChooseUISnapScrollRect : MonoBehaviour, IEndDragHandler
{
public RectTransform content; // 自动寻找 Viewport/List
public float snapSpeed = 10f; // 平滑速度
public float snapThreshold = 0.1f; // 靠近这个范围就停止
public float itemHeight = 60f; // 每项高度(固定)
private ScrollRect scrollRect;
private bool isSnapping = false;
private int itemCount = 0;
public int selectedIndex = -1;
void Start()
{
scrollRect = GetComponent<ScrollRect>();
scrollRect.horizontal = false;
scrollRect.vertical = true;
// 自动寻找 Viewport/List
if (content == null)
{
Transform viewport = transform.Find("Viewport");
if (viewport != null)
{
Transform list = viewport.Find("List");
if (list != null)
{
content = list.GetComponent<RectTransform>();
scrollRect.content = content;
}
else
{
Debug.LogError($"{name}: 找不到 Viewport/List");
}
}
else
{
Debug.LogError($"{name}: 找不到 Viewport");
}
}
if (content != null)
{
itemCount = content.childCount;
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (!isSnapping && content != null)
{
StartCoroutine(SnapToClosestItem());
}
}
IEnumerator SnapToClosestItem()
{
isSnapping = true;
float currentY = content.anchoredPosition.y;
int closestIndex = Mathf.RoundToInt(currentY / itemHeight);
closestIndex = Mathf.Clamp(closestIndex, 0, itemCount - 1);
selectedIndex = closestIndex;
float targetY = closestIndex * itemHeight;
while (Mathf.Abs(content.anchoredPosition.y - targetY) > snapThreshold)
{
float newY = Mathf.Lerp(content.anchoredPosition.y, targetY, Time.deltaTime * snapSpeed);
content.anchoredPosition = new Vector2(content.anchoredPosition.x, newY);
yield return null;
}
content.anchoredPosition = new Vector2(content.anchoredPosition.x, targetY);
HighlightSelectedItem(closestIndex);
isSnapping = false;
}
private void HighlightSelectedItem(int selected)
{
for (int i = 0; i < itemCount; i++)
{
var option = content.GetChild(i);
var tmp = option.GetComponent<TMPro.TextMeshProUGUI>();
if (tmp != null)
{
tmp.color = (i == selected)
? new Color32(0xFF, 0xFF, 0xFF, 255) // #FFFFFF
: new Color32(0x78, 0x78, 0x78, 255); // #787878
continue;
}
var uiText = option.GetComponent<Text>();
if (uiText != null)
{
uiText.color = (i == selected)
? new Color32(0xFF, 0xFF, 0xFF, 255)
: new Color32(0x78, 0x78, 0x78, 255);
}
}
}
// 可手动吸附到某一项
public void SnapToIndex(int index)
{
index = Mathf.Clamp(index, 0, itemCount - 1);
float targetY = index * itemHeight;
content.anchoredPosition = new Vector2(content.anchoredPosition.x, targetY);
selectedIndex = index;
HighlightSelectedItem(index);
}
}
}

View File

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

View File

@ -8,9 +8,9 @@ namespace UI.Common{
{
public AnimationClip popupClip;
public AnimationClip popinClip;
public Color normalColor = Color.white;
public Color highlightColor = Color.yellow;
public Color LockedColor = Color.gray;
public Color normalColor;
public Color highlightColor;
public Color LockedColor;
public bool IsLocked = false;
private Image _image;
private Image _buttonImage;
@ -33,7 +33,7 @@ namespace UI.Common{
public void OnPointerEnter(PointerEventData eventData)
{
if (IsLocked) return;
if (_image != null) _image.color = highlightColor;
if (_image != null) _buttonImage.color = highlightColor;
if (popupClip != null && _animancer != null)
{
_animancer.Play(popupClip);
@ -43,7 +43,7 @@ namespace UI.Common{
public void OnPointerExit(PointerEventData eventData)
{
if (IsLocked) return;
if (_image != null) _image.color = normalColor;
if (_image != null) _buttonImage.color = normalColor;
if (popinClip != null && _animancer != null)
{
_animancer.Play(popinClip);

View File

@ -0,0 +1,155 @@
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class TribeHoverEffect : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
private Image maskImage;
private Image selectImage;
private GameObject selectedObject;
private Button button;
private bool isSelected = false;
private Color highlightColor = new Color32(0x2A, 0xFF, 0x00, 255); // #2AFF00
private Color defaultColor = new Color32(0x88, 0x88, 0x88, 255); // #888888
private byte normalAlpha = 150;
private byte hoverAlpha = 200;
private byte selectedAlpha = 255;
public bool IsLocked;
void Awake()
{
// 自动获取 UI 组件
maskImage = transform.Find("TribeIconMask/Mask")?.GetComponent<Image>();
selectImage = transform.Find("TribeIconMask/Select")?.GetComponent<Image>();
selectedObject = transform.Find("TribeIconMask/Select/Selected")?.gameObject;
// 获取同节点的 Button
button = GetComponent<Button>();
}
void Start()
{
// 自动选中同级中第一个拥有 TribeHoverEffect 的对象
if (IsFirstTribeInParent())
{
OnClicked(); // 默认选中
}
else
{
if (!isSelected)
{
ApplyNormalState();
if (selectedObject != null)
selectedObject.SetActive(false);
}
}
// 如果有 Button则通过代码绑定点击事件
if (button != null)
{
button.onClick.AddListener(HandleButtonClick);
}
}
private bool IsFirstTribeInParent()
{
Transform parent = transform.parent;
if (parent == null) return false;
foreach (Transform child in parent)
{
var effect = child.GetComponent<TribeHoverEffect>();
if (effect != null)
{
return child == transform; // 第一个找到的就是自己
}
}
return false;
}
// 供 Button 调用的封装
public void HandleButtonClick()
{
if(!IsLocked)
OnClicked();
}
private void OnClicked()
{
// 取消兄弟节点选中
Transform parent = transform.parent;
if (parent != null)
{
foreach (Transform child in parent)
{
if (child == transform) continue;
var effect = child.GetComponent<TribeHoverEffect>();
if (effect != null)
{
effect.Deselect();
}
}
}
// 自身设为选中
isSelected = true;
selectImage.color = highlightColor;
SetAlpha(maskImage, selectedAlpha);
if (selectedObject != null)
selectedObject.SetActive(true);
}
public void OnPointerEnter(PointerEventData eventData)
{
if (IsLocked) return;
if (!isSelected)
{
selectImage.color = highlightColor;
SetAlpha(maskImage, hoverAlpha);
}
}
public void OnPointerExit(PointerEventData eventData)
{
if (IsLocked) return;
if (!isSelected)
{
selectImage.color = defaultColor;
SetAlpha(maskImage, normalAlpha);
}
}
private void ApplyNormalState()
{
if (selectImage != null)
selectImage.color = defaultColor;
SetAlpha(maskImage, normalAlpha);
}
private void SetAlpha(Image image, byte alpha)
{
if (image == null) return;
Color color = image.color;
color.a = alpha / 255f;
image.color = color;
}
public void Deselect()
{
isSelected = false;
ApplyNormalState();
if (selectedObject != null)
selectedObject.SetActive(false);
}
public bool CheckIsSelected()
{
return isSelected;
}
}

View File

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

View File

@ -33,11 +33,11 @@ public class MainUI
ROMainUI.gameObject.SetActive(false);
// 绑定所有按钮
NewGameButton = ROMainUI.transform.Find("ButtonRow/NewGameButton/MainUIButton/Button").GetComponent<Button>();
ResumeGameButton = ROMainUI.transform.Find("ButtonRow/ResumeGameButton/MainUIButton/Button").GetComponent<Button>();
StoryModeButton = ROMainUI.transform.Find("ButtonRow/StoryModeButton/MainUIButton/Button").GetComponent<Button>();
LibraryButton = ROMainUI.transform.Find("ButtonRow/LibraryButton/MainUIButton/Button").GetComponent<Button>();
HistoryButton = ROMainUI.transform.Find("ButtonRow/HistoryButton/MainUIButton/Button").GetComponent<Button>();
NewGameButton = ROMainUI.transform.Find("ButtonRow/NewGameButton/MainUIButton").GetComponent<Button>();
ResumeGameButton = ROMainUI.transform.Find("ButtonRow/ResumeGameButton/MainUIButton").GetComponent<Button>();
StoryModeButton = ROMainUI.transform.Find("ButtonRow/StoryModeButton/MainUIButton").GetComponent<Button>();
LibraryButton = ROMainUI.transform.Find("ButtonRow/LibraryButton/MainUIButton").GetComponent<Button>();
HistoryButton = ROMainUI.transform.Find("ButtonRow/HistoryButton/MainUIButton").GetComponent<Button>();
SettingButton = ROMainUI.transform.Find("ButtonRow2/SettingButton").GetComponent<Button>();
AboutButton = ROMainUI.transform.Find("ButtonRow2/AboutButton").GetComponent<Button>();