ngui 做卡牌特效
在游戏开发中,卡牌特效是一个常见且有趣的功能。本文将详细介绍如何使用NGUI(Next-Gen UI)来实现卡牌特效。虽然刚开始接触可能会有一定难度,但随着学习的深入,你会发现很多东西会变得越来越简单。
卡牌特效概述
我们实现了两个卡牌特效,包含三种效果:
- 横向特效:点击相应卡牌,将点击的卡牌置顶。
- 竖向特效:点击卡片,卡片突出并置顶,同时伴有移动效果。
- 发牌特效:具体效果可查看工程。
横向与竖向特效展示
横向特效和竖向特效在视觉上有明显区别。若要将特效修改为竖向,只需将特定标志量设置为true。
代码实现
代码示例
以下是实现上述卡牌特效的完整代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class SceneLuckyCard : MonoBehaviour
{
#region 数据定义
// 存储卡牌名称的列表
private List<string> mNameList = new List<string>();
// 卡牌预制体
private GameObject mItem;
// 移动面板
private UIPanel mMovePanel;
// 卡牌效果偏移量
private int CardEffectOffset = 80;
// 存储所有卡牌的列表
public List<GameObject> cardList;
// 当前选中的卡牌索引
private int indexCard;
// 卡牌总数
private int cardCount;
// 最大深度
private int maxDepth = 50;
// 当前选中卡牌的位置
private Vector3 indexPosition;
// 动画时间间隔
public float timeSpan = 0.2f;
// 是否使用协程标志
public bool isIEnum = true;
// 存储所有卡牌位置的列表
private List<Vector3> posList;
// 卡牌偏移量
public Vector2 offsetCard = new Vector2(20f, 100f);
/// <summary> 是否竖向 </summary>
public bool direction = false;
#endregion
// 初始化方法
void Start ()
{
// 通过路径获取卡牌预制体
mItem = PublicFunction.GetComponentByLocalPath<Transform>(this.gameObject, "PanelMove/Items/Item").gameObject;
// 通过路径获取移动面板
mMovePanel = PublicFunction.GetComponentByLocalPath<UIPanel>(this.gameObject, "PanelMove");
// 添加卡牌名称
mNameList.Add("德玛西亚");
mNameList.Add("皮城女警");
mNameList.Add("影流之主");
mNameList.Add("末日浩劫");
mNameList.Add("荒野屠夫");
mNameList.Add("刀锋之影");
mNameList.Add("提莫对账");
mNameList.Add("麦林炮手");
mNameList.Add("荒野屠夫");
mNameList.Add("刀锋之影");
// 开始克隆卡牌的协程
StartCoroutine(CloneItem(mNameList.Count));
// 输出卡牌名称列表的数量
Debug.LogError(mNameList.Count);
// 初始化当前选中卡牌的索引
indexCard = mNameList.Count - 1;
// 初始化卡牌总数
cardCount = mNameList.Count;
}
// 克隆卡牌的协程
IEnumerator CloneItem(int num)
{
// 如果卡牌数量大于等于9,调整卡牌效果偏移量
if (num >= 9)
{
CardEffectOffset -= 15;
}
// 循环克隆卡牌
for (int i = 0; i < num; i++)
{
// 实例化卡牌预制体
GameObject item = Instantiate(mItem) as GameObject;
// 设置卡牌的父对象
item.transform.parent = mItem.transform.parent;
// 设置卡牌的欧拉角
item.transform.localEulerAngles = Vector3.zero;
// 设置卡牌的缩放
item.transform.localScale = Vector3.one;
// 设置卡牌的初始位置
item.transform.localPosition = new Vector3(-900, 0, 0);
// 设置卡牌的名称
item.name = i.ToString();
// 将卡牌添加到卡牌列表中
cardList.Add(item);
// 为卡牌添加点击事件监听器
UIEventListener listener = UIEventListener.Get(item);
listener.onClick = OnClickCard;
// 等待一段时间
yield return new WaitForSeconds(0.2f);
// 执行卡牌飞行效果
FlightEffect(i, item);
}
// 清空或初始化位置列表
if (posList != null && posList.Count > 0)
{
posList.Clear();
}
else
{
posList = new List<Vector3>();
}
// 存储所有卡牌的位置
foreach (GameObject go in cardList)
{
posList.Add(go.transform.localPosition);
}
}
// 卡牌飞行效果方法
void FlightEffect(int index, GameObject item)
{
// 为卡牌添加位置移动组件
TweenPosition tp = item.AddComponent<TweenPosition>();
// 设置移动起始位置
tp.from = item.transform.localPosition;
// 设置移动结束位置
tp.to = new Vector3(300 - (CardEffectOffset * index), item.transform.localPosition.y, 0);
// 设置移动持续时间
tp.duration = 0.2f;
// 获取卡牌及其子对象的所有UI组件
UIWidget[] tran = item.GetComponentsInChildren<UIWidget>(true);
// 调整每个UI组件的深度
foreach (UIWidget tra in tran)
{
tra.depth += (index * 5);
}
}
// 卡牌点击事件处理方法
void OnClickCard(GameObject go)
{
int tempindex = 0;
// 查找点击卡牌的索引
for (int i = 0; i < cardList.Count; i++)
{
if (cardList[i].name == go.name)
{
tempindex = i;
break;
}
}
// 如果点击的不是当前选中的卡牌
if (tempindex != indexCard)
{
// 更新当前选中卡牌的索引
indexCard = tempindex;
// 获取点击卡牌的UI组件
UIWidget uw = go.GetComponent<UIWidget>();
// 设置点击卡牌的深度为最大深度
uw.depth = maxDepth;
// 设置点击卡牌的颜色为白色
uw.color = Color.white;
// 设置点击卡牌的目标位置
indexPosition = new Vector3(0, go.transform.localPosition.y, 0);
// 如果是竖向模式,执行位置移动动画
if (direction)
{
TweenPosition.Begin(go, timeSpan, indexPosition);
}
// 开始设置卡牌顺序的协程
StartCoroutine(SetCardOrder(timeSpan / 2f, isIEnum, direction));
// 设置卡牌的深度
SetDepth(uw.depth, go);
}
}
// 重载的设置卡牌顺序方法
public void SetCardOrder()
{
// 可调用协程方法
// StartCoroutine(SetCardOrder(0.01f, false));
}
// 设置卡牌顺序的协程
public IEnumerator SetCardOrder(float span, bool isienum, bool erect)
{
int tempDepth = maxDepth;
// 处理当前选中卡牌之前的卡牌
if (indexCard > 0)
{
for (int i = indexCard; i > 0; --i)
{
Vector3 tempPos = indexPosition;
if (i != indexCard)
{
tempPos = posList[i];
}
GameObject go = cardList[i - 1];
// 如果是竖向模式,执行位置移动动画
if (erect)
{
posList[i - 1] = new Vector3(tempPos.x + offsetCard.x, tempPos.y + offsetCard.y, tempPos.z);
TweenPosition.Begin(go, timeSpan, posList[i - 1]);
}
// 获取卡牌的UI组件
UIWidget uw = go.GetComponent<UIWidget>();
if (uw != null)
{
// 调整深度
tempDepth -= 5;
uw.depth = tempDepth;
}
// 设置卡牌的深度
SetDepth(uw.depth, go);
// 如果需要等待,等待一段时间
// if (isienum) yield return new WaitForSeconds(span);
}
tempDepth = maxDepth;
}
// 处理当前选中卡牌之后的卡牌
if (indexCard < cardList.Count - 1)
{
for (int i = indexCard; i < cardCount - 1; ++i)
{
Vector3 tempPos = indexPosition;
if (i != indexCard)
{
tempPos = posList[i];
}
GameObject go = cardList[i + 1];
// 如果是竖向模式,执行位置移动动画
if (erect)
{
posList[i + 1] = new Vector3(tempPos.x + offsetCard.x, tempPos.y - offsetCard.y, tempPos.z);
TweenPosition.Begin(go, timeSpan, posList[i + 1]);
}
// 获取卡牌的UI组件
UIWidget uw = go.GetComponent<UIWidget>();
if (uw != null)
{
// 调整深度
tempDepth -= 5;
uw.depth = tempDepth;
}
// 设置卡牌的深度
SetDepth(uw.depth, go);
// 如果需要等待,等待一段时间
// if (isienum) yield return new WaitForSeconds(span);
}
}
yield return 1;
}
// 设置卡牌深度的方法
void SetDepth(int parentDepth, GameObject obj)
{
// 获取卡牌子对象的UILabel组件并设置深度
PublicFunction.GetComponentByLocalPath<UILabel>(obj, "Label").depth = parentDepth + 1;
// 获取卡牌子对象的UISprite组件并设置深度
PublicFunction.GetComponentByLocalPath<UISprite>(obj, "Time").depth = parentDepth + 1;
// 获取卡牌子对象的UILabel组件并设置深度
PublicFunction.GetComponentByLocalPath<UILabel>(obj, "Time/Label").depth = parentDepth + 1;
}
}
代码解释
- 数据定义部分:定义了各种变量,包括卡牌名称列表、预制体、面板、偏移量、卡牌列表等,用于存储和管理卡牌相关的数据。
Start方法:在游戏开始时初始化卡牌预制体、移动面板,添加卡牌名称,启动克隆卡牌的协程,并记录卡牌总数和当前选中卡牌的索引。CloneItem协程:根据卡牌数量调整偏移量,克隆卡牌并设置其属性,添加点击事件监听器,执行飞行效果,最后存储所有卡牌的位置。FlightEffect方法:为卡牌添加位置移动组件,设置移动起始和结束位置,调整卡牌及其子对象的UI组件深度。OnClickCard方法:处理卡牌点击事件,更新当前选中卡牌的索引,设置点击卡牌的深度和颜色,执行位置移动动画,启动设置卡牌顺序的协程。SetCardOrder协程:根据当前选中卡牌的索引,调整其他卡牌的位置和深度,实现卡牌的排序效果。SetDepth方法:设置卡牌及其子对象的UI组件的深度。
通过以上代码和解释,你可以使用NGUI实现具有横向、竖向特效和发牌特效的卡牌系统。在实际应用中,你可以根据需求对代码进行进一步的修改和扩展。