Unity实现杀戮尖塔出牌效果(一.扇形开牌)

最终效果展示

主要步骤

一. 扇形开牌

二. 鼠标指向卡牌时,卡牌强调动画

①卡牌高度提升
②卡牌旋转归零
③卡牌层级高于其他手牌

三. 卡牌使用效果

1. 攻击类型卡牌

①拖拽超过一定高度之后卡牌会移动到手牌中心位置
②出现攻击引导箭头
③成功指向目标怪物后打出

2. 技能能力类型卡牌

①可自由拖动
②脱离手牌高度后打出

四. 卡牌使用结束效果

1. 播放攻击特效

2. 播放卡牌收尾特效

①卡牌从当前位置移动到中心位置
②卡牌居中悬停展示几毫秒
③播放回归弃牌堆动画

代码详解

一. 扇形开牌

在这里插入图片描述

核心代码

public class CardItem : MonoBehaviour  
{  
    /// <summary>  
    /// 卡牌扇形展开中心点  
    /// </summary>  
    public Vector3 root;  
    /// <summary>  
    /// 展开角度  
    /// </summary>  
    public float rot;  
    /// <summary>  
    /// 展开半径  
    /// </summary>  
    public float size;  
    /// <summary>  
    /// 动画速度  
    /// </summary>  
    public float animSpeed = 10;  
    /// <summary>  
    /// 高度值(决定卡牌层级)  
    /// </summary>  
    public float zPos=0;  
  
  
    public  void RefreshData(Vector3 root,float rot, float size,float zPos)  
    {        
        this.root = root;  
        this.rot = rot;  
        this.size = size;  
        this.zPos = -zPos*0.02f;  
    }  
    // Update is called once per frame  
    void Update()  
    {        
        SetPos();  
    }  
    public void SetPos()  
    {        
        //设置卡牌位置  
        float x = root.x + Mathf.Cos(rot) * size;  
        float y = root.y + Mathf.Sin(rot) * size;  
        transform.position = Vector3.Lerp(transform.position, new Vector3(x, y, root.z+this.zPos), Time.deltaTime * animSpeed);  
        //设置卡牌角度  
        float rotZ = GetAngleInDegrees(root, transform.position);  
        Vector3 localEulerAngles = transform.localEulerAngles;  
        Quaternion rotationQuaternion = Quaternion.Euler(new Vector3(0, 0, rotZ));  
        transform.rotation = Quaternion.RotateTowards(transform.rotation, rotationQuaternion, Time.deltaTime * animSpeed * 30);  
    }    
    /// <summary>  
    /// 获取两个向量之间的弧度值0-2π  
    /// </summary>    /// <param name="positionA">点A坐标</param>  
    /// <param name="positionB">点B坐标</param>  
    /// <returns></returns>    
    public static float GetAngleInDegrees(Vector3 positionA, Vector3 positionB)  
    {        
        // 计算从A指向B的向量  
        Vector3 direction = positionB - positionA;  
        // 将向量标准化  
        Vector3 normalizedDirection = direction.normalized;  
        // 计算夹角的弧度值  
        float dotProduct = Vector3.Dot(normalizedDirection, Vector3.up);  
        float angleInRadians = Mathf.Acos(dotProduct);  
  
        //判断夹角的方向:通过计算一个参考向量与两个物体之间的叉乘,可以确定夹角是顺时针还是逆时针方向。这将帮助我们将夹角的范围扩展到0到360度。  
        Vector3 cross = Vector3.Cross(normalizedDirection, Vector3.up);  
        if (cross.z > 0)  
        {            
           angleInRadians = 2 * Mathf.PI - angleInRadians;  
        }  
        // 将弧度值转换为角度值  
        float angleInDegrees = angleInRadians * Mathf.Rad2Deg;  
        return angleInDegrees;  
    }}
public class CardManager : MonoBehaviour  
{  
    /// <summary>  
    /// 卡牌起始位置  
    /// </summary>  
    public Vector3 rootPos=new Vector3(0,-33.5f,20);  
    /// <summary>  
    /// 卡牌对象  
    /// </summary>  
    public GameObject cardItem;  
    /// <summary>  
    /// 扇形半径  
    /// </summary>  
    public float size =30f;  
    /// <summary>  
    /// 卡牌出现最大位置  
    /// </summary>  
    private float minPos = 1.415f;  
    /// <summary>  
    /// 卡牌出现最小位置  
    /// </summary>  
    private float maxPos = 1.73f;  
    /// <summary>  
    /// 手牌列表  
    /// </summary>  
    private List<CardItem> cardList;  
    /// <summary>  
    /// 手牌位置  
    /// </summary>  
    private List<float> rotPos;  
    /// <summary>  
    /// 最大手牌数量  
    /// </summary>  
    private int CardMaxCount=8;  
  
    void Start()  
    {        InitCard();  
    }    /// <summary>  
    /// 数据初始化  
    /// </summary>  
    public  void InitCard()  
    {  
          rotPos=InitRotPos(CardMaxCount);  
    }    
    /// <summary>  
    /// 初始化位置  
    /// </summary>  
    /// <param name="count"></param>    
    /// <param name="interval"></param>    
    /// <returns></returns>    
    public List<float> InitRotPos(int count)  
    {        
        List<float> rotPos=new List<float>();  
        float interval = (maxPos - minPos)/count;  
        for (int i = 0; i < count; i++)  
        {            
            float nowPos = maxPos - interval * i;  
            rotPos.Add(nowPos);  
        }        
        return rotPos;  
    }  
    // Update is called once per frame  
    void Update()  
    {        
        TaskItemDetection();  
        RefereshCard();  
    }   
    /// <summary>  
    /// 添加卡牌  
    /// </summary>  
    public  void AddCard()  
    {        
        if (cardList==null)  
        {            
            cardList=new List<CardItem>();  
        }  
        if (cardList.Count>=CardMaxCount)  
        {            
            Debug.Log("手牌数量上限");  
            return;  
        }        
        GameObject item = Instantiate(cardItem,this.transform);  
        CardItem text=item.GetComponent<CardItem>();  
        text.RefreshData(rootPos,0,0,0);  
        cardList.Add(text);  
    }    
    /// <summary>  
    /// 手牌状态刷新  
    /// </summary>  
    public void RefereshCard()  
    {        
        if (cardList==null)  
        {            
           return;  
        }  
        for (int i = 0; i < cardList.Count; i++)  
        {
            cardList[i].RefreshData(rootPos,rotPos[i],size,i);   
        }  
    }    
    /// <summary>  
    /// 销毁卡牌  
    /// </summary>  
    public  void RemoveCard()  
    {        
        if (cardList==null)  
        {
            return;  
        }  
        CardItem item = cardList[cardList.Count - 1];  
        cardList.Remove(item);  
        Destroy(item.gameObject);  
    }    
	/// <summary>  
    /// 销毁卡牌  
    /// </summary>  
    /// <param name="item"></param>    
    public  void RemoveCard(CardItem item)  
    {        
        if (cardList==null)  
        {
	        return;  
        }
        cardList.Remove(item);  
        Destroy(item.gameObject);  
    }  
    private Vector3 oldmousePosition;  
          
    /// <summary>  
    /// 玩家操作检测  
    /// </summary>  
    public void TaskItemDetection()  
    {       
       if (Input.GetKeyDown(KeyCode.A))  
        {         
           AddCard();  
        }          
     }  
}
Unity实现这种效果,你需要结合UI系统、Transform组件以及碰撞检测功能。下面是个基本的步骤: 1. 首先,在每个上添加个UI元件(如Image或CanvasRenderer),用于显示手图像。确保它有个透明度或Alpha值,以便实现渐变放大效果。 2. 在手物体上使用`RectTransform`组件,这有助于获取每个的位置和大小,以及它们之间的相对关系。 3. 当鼠标移到某个上时,获取当前鼠标位置相对于屏幕的像素坐标,并将其转换为 RectTransform 的世界空间坐标。这可以通过`ScreenToWorldPoint`函数完成。 4. 使用这个世界空间坐标去测试之间的遮挡。你可以创建个矩形区域,其大小等于当前选中的尺寸,然后检查该区域是否与其它有交集。`OverlapArea`函数可以用来检测碰撞。 5. 如果测试结果显示不存在遮挡,那么执行选择判定;否则,忽略这次判定。 以下是伪代码示例: ```csharp void OnMouseMove(Vector2 mousePosition) { RectTransform hitTransform = GetHitTransform(mousePosition); if (!hitTransform.rect.Contains(mousePosition) && !CheckForCollision(hitTransform)) { PerformSelection(); } } private RectTransform GetHitTransform(Vector2 screenPosition) { Vector3 worldPosition = Camera.main.ScreenToWorldPoint(screenPosition); return Get RectTransformAtWorldPosition(worldPosition); } private bool CheckForCollision(RectTransform target) { foreach (RectTransform other in HandCards) { if (other != target && other.rect.Intersects(target.rect)) { return true; } } return false; } private void PerformSelection() { // 进行选择判定操作 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值