技能主要更新,修复卡顿并加入动画,以及各种其他更新。
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class CharacterCardView : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
|
||||
public class CharacterCardView : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler,
|
||||
IPointerEnterHandler, IPointerExitHandler, IPointerMoveHandler
|
||||
{
|
||||
public int characterID;
|
||||
public string currentBoundaryLevel;
|
||||
@@ -19,12 +21,38 @@ public class CharacterCardView : MonoBehaviour, IBeginDragHandler, IDragHandler,
|
||||
private GameObject dragGhost;
|
||||
private Canvas rootCanvas;
|
||||
private CanvasGroup canvasGroup;
|
||||
private LayoutElement layoutElement;
|
||||
|
||||
[Header("Hover Anim")]
|
||||
[SerializeField] bool enableHoverAnim = true;
|
||||
[SerializeField] float hoverScale = 1.06f;
|
||||
[SerializeField] float hoverTweenTime = 0.12f;
|
||||
[SerializeField] float hoverExpand = 0.18f;
|
||||
[SerializeField] float hoverCompress = 0.08f;
|
||||
[SerializeField] float gyroMaxAngle = 6f;
|
||||
[SerializeField] float gyroFollow = 8f;
|
||||
|
||||
private bool isHovering;
|
||||
private bool isDragging;
|
||||
private Camera lastEventCamera;
|
||||
|
||||
class LayoutInfo
|
||||
{
|
||||
public CharacterCardView card;
|
||||
public LayoutElement layout;
|
||||
public float baseSize;
|
||||
}
|
||||
|
||||
static readonly Dictionary<Transform, List<LayoutInfo>> layoutCache = new();
|
||||
static readonly Dictionary<Transform, bool> layoutAxisIsHorizontal = new();
|
||||
|
||||
void Start()
|
||||
{
|
||||
charactCard = gameObject;
|
||||
rootCanvas = GetComponentInParent<Canvas>();
|
||||
canvasGroup = GetComponent<CanvasGroup>() ?? gameObject.AddComponent<CanvasGroup>();
|
||||
layoutElement = GetComponent<LayoutElement>() ?? gameObject.AddComponent<LayoutElement>();
|
||||
if (characterImage != null) characterImage.raycastTarget = true;
|
||||
}
|
||||
/// <summary>
|
||||
/// 未在队中的卡点击后进入被操纵状态。若在队伍中默认进入已经入队状态
|
||||
@@ -59,6 +87,13 @@ public class CharacterCardView : MonoBehaviour, IBeginDragHandler, IDragHandler,
|
||||
// prevent the original from blocking raycasts so drop targets can receive events
|
||||
if (canvasGroup == null) canvasGroup = GetComponent<CanvasGroup>() ?? gameObject.AddComponent<CanvasGroup>();
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
canvasGroup.alpha = 0f;
|
||||
isDragging = true;
|
||||
ApplyHoverLayout(false);
|
||||
StopHoverEffects();
|
||||
if (layoutElement == null) layoutElement = GetComponent<LayoutElement>() ?? gameObject.AddComponent<LayoutElement>();
|
||||
layoutElement.ignoreLayout = true;
|
||||
ForceRebuildParentLayout();
|
||||
|
||||
// ensure pointerDrag references this object for drop handlers
|
||||
eventData.pointerDrag = gameObject;
|
||||
@@ -93,6 +128,12 @@ public class CharacterCardView : MonoBehaviour, IBeginDragHandler, IDragHandler,
|
||||
// restore raycast blocking on the original
|
||||
if (canvasGroup != null)
|
||||
canvasGroup.blocksRaycasts = true;
|
||||
if (canvasGroup != null)
|
||||
canvasGroup.alpha = 1f;
|
||||
if (layoutElement != null)
|
||||
layoutElement.ignoreLayout = false;
|
||||
isDragging = false;
|
||||
ForceRebuildParentLayout();
|
||||
}
|
||||
|
||||
private void UpdateGhostPosition(PointerEventData eventData)
|
||||
@@ -106,4 +147,125 @@ public class CharacterCardView : MonoBehaviour, IBeginDragHandler, IDragHandler,
|
||||
if (dragGhost != null)
|
||||
dragGhost.transform.localPosition = localPoint;
|
||||
}
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
if (!enableHoverAnim || isDragging) return;
|
||||
isHovering = true;
|
||||
lastEventCamera = eventData.enterEventCamera;
|
||||
ApplyHoverLayout(true);
|
||||
transform.DOKill();
|
||||
transform.DOScale(hoverScale, hoverTweenTime).SetEase(Ease.OutCubic);
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
if (!enableHoverAnim) return;
|
||||
isHovering = false;
|
||||
ApplyHoverLayout(false);
|
||||
StopHoverEffects();
|
||||
}
|
||||
|
||||
public void OnPointerMove(PointerEventData eventData)
|
||||
{
|
||||
if (!enableHoverAnim) return;
|
||||
lastEventCamera = eventData.enterEventCamera;
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (!enableHoverAnim || !isHovering || isDragging) return;
|
||||
RectTransform rt = transform as RectTransform;
|
||||
if (rt == null) return;
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rt, Input.mousePosition, lastEventCamera, out Vector2 localPoint))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Vector2 size = rt.rect.size;
|
||||
if (size.x <= 0f || size.y <= 0f) return;
|
||||
Vector2 norm = new Vector2(localPoint.x / size.x, localPoint.y / size.y);
|
||||
norm = Vector2.ClampMagnitude(norm * 2f, 1f);
|
||||
float xRot = -norm.y * gyroMaxAngle;
|
||||
float yRot = norm.x * gyroMaxAngle;
|
||||
Quaternion target = Quaternion.Euler(xRot, yRot, 0f);
|
||||
transform.localRotation = Quaternion.Slerp(transform.localRotation, target, Time.unscaledDeltaTime * gyroFollow);
|
||||
}
|
||||
|
||||
void StopHoverEffects()
|
||||
{
|
||||
transform.DOKill();
|
||||
transform.DOScale(1f, hoverTweenTime).SetEase(Ease.OutCubic);
|
||||
transform.localRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
void ApplyHoverLayout(bool active)
|
||||
{
|
||||
Transform parent = transform.parent;
|
||||
if (parent == null) return;
|
||||
List<LayoutInfo> group = GetOrCacheGroup(parent);
|
||||
if (group == null || group.Count == 0) return;
|
||||
|
||||
bool horizontal = layoutAxisIsHorizontal.TryGetValue(parent, out bool h) ? h : true;
|
||||
for (int i = 0; i < group.Count; i++)
|
||||
{
|
||||
LayoutInfo info = group[i];
|
||||
if (info == null || info.layout == null) continue;
|
||||
float baseSize = info.baseSize;
|
||||
float target = baseSize;
|
||||
if (active)
|
||||
{
|
||||
target = info.card == this
|
||||
? baseSize * (1f + hoverExpand)
|
||||
: baseSize * Mathf.Max(0.1f, 1f - hoverCompress);
|
||||
}
|
||||
if (horizontal)
|
||||
info.layout.preferredWidth = target;
|
||||
else
|
||||
info.layout.preferredHeight = target;
|
||||
}
|
||||
ForceRebuildParentLayout();
|
||||
}
|
||||
|
||||
List<LayoutInfo> GetOrCacheGroup(Transform parent)
|
||||
{
|
||||
if (layoutCache.TryGetValue(parent, out var cached) && cached != null && cached.Count > 0)
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
|
||||
bool horizontal = parent.GetComponent<HorizontalLayoutGroup>() != null;
|
||||
bool vertical = parent.GetComponent<VerticalLayoutGroup>() != null;
|
||||
layoutAxisIsHorizontal[parent] = !vertical || horizontal;
|
||||
|
||||
var list = new List<LayoutInfo>();
|
||||
CharacterCardView[] cards = parent.GetComponentsInChildren<CharacterCardView>(true);
|
||||
for (int i = 0; i < cards.Length; i++)
|
||||
{
|
||||
var card = cards[i];
|
||||
if (card == null) continue;
|
||||
var le = card.layoutElement ?? card.GetComponent<LayoutElement>() ?? card.gameObject.AddComponent<LayoutElement>();
|
||||
RectTransform rt = card.transform as RectTransform;
|
||||
float baseSize = 100f;
|
||||
if (rt != null)
|
||||
{
|
||||
baseSize = horizontal ? rt.rect.width : rt.rect.height;
|
||||
}
|
||||
if (horizontal)
|
||||
le.preferredWidth = baseSize;
|
||||
else
|
||||
le.preferredHeight = baseSize;
|
||||
|
||||
list.Add(new LayoutInfo { card = card, layout = le, baseSize = baseSize });
|
||||
}
|
||||
layoutCache[parent] = list;
|
||||
return list;
|
||||
}
|
||||
|
||||
void ForceRebuildParentLayout()
|
||||
{
|
||||
if (transform.parent == null) return;
|
||||
RectTransform prt = transform.parent as RectTransform;
|
||||
if (prt != null)
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(prt);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user