近战攻击的贴花方向(Quaternion)问题

2近战攻击,加入拿的看到,砍在墙上地上要有痕迹的粒子效果.

关于贴花需要做到位置和旋转的改变.

1,位置位于碰撞到的位置.
2,旋转应该是位于碰撞点的法线.
3,碰撞点的法线只是向上的,并没有旋转,那么我们希望它能够面朝玩家.

我做了下面的测试效果.

using UnityEngine;
using System.Collections;

public class CTestNormal : MonoBehaviour
{

    public Transform pic;
    public Transform pic2;

    float t = 0f;

    void Update()
    {
        //if (Time.time < t)
          //  return;
        //t = Time.time + 1f;
        Vector3 at = transform.position;
        RaycastHit targetHit;

        bool raytrigger = Physics.Raycast(at, transform.forward, out targetHit);
        if (!raytrigger)
            return;

        float dis = Vector3.Distance(targetHit.point, transform.position);
        Debug.DrawRay(at, transform.forward * dis, Color.blue);

        Debug.DrawRay(pic.position + pic.forward * 0.05f, pic.forward, Color.blue); // 绘制每根轴
        Debug.DrawRay(pic.position + pic.forward * 0.05f, pic.right, Color.red);
        Debug.DrawRay(pic.position + pic.forward * 0.05f, pic.up, Color.green);

        Quaternion normal = Quaternion.LookRotation( targetHit.normal); //打到墙上的射线旋转
        //计算贴花在墙面的投影向量
        Vector3 rot = Vector3.Cross(targetHit.normal, -transform.forward);   //算垂直于墙面法线和攻击方向的向量

        //Vector3 touyingV3 = Vector3.Cross(targetHit.normal, rot); // 向量的投影

        touying.transform.forward = touyingV3;

        Quaternion rot2 = Quaternion.LookRotation(touyingV3);   //转为角度
        Vector3 er = Vector3.zero;

        er.z = rot2.eulerAngles.x +90f;   //对于rot2的x轴的旋转正好是看向发射点的z轴旋转 + 90f , 转到贴花的方向.
        
        normal.eulerAngles  += er;

        pic.eulerAngles = normal;
        pic.transform.position = targetHit.point;

        pic2.eulerAngles = rot.eulerAngles;
        pic2.transform.position = targetHit.point;
       
    }
}

图1
如图1: 红色是地面,蓝色是墙.
1,黄色的类似长方形我们假定是攻击的特效.图中的蓝色,绿色,红色线是代码里绘制的,代表了他的坐标轴.
2,黄绿色的一个永远面向胶囊的,是一个对比看效果,Scene中的箭头是我选中的黄绿色的transform显示出来的.

实现方法就是先计算法线旋转,然后再把朝向玩家的旋转附加给他,就简单实现了.

图2:地面效果
这里写图片描述


-------------------------------------------------------------------------华丽的分割线-------------------------------------------------------


上面的例子经过测试有很多不足,如果在斜方向砍墙, 贴花的角度就有问题了,下面进行了优化.

using UnityEngine;
using System.Collections;

public class CTestNormal : MonoBehaviour
{

    public Transform flower;
    public Transform pic2;
    public Transform phyDir;
    public Transform phyDirChuizhi;
    public Transform touying;
    float t = 0f;

    void Update()
    {
        //if (Time.time < t)
          //  return;
        //t = Time.time + 1f;
        Vector3 at = transform.position;
        RaycastHit targetHit;

        bool raytrigger = Physics.Raycast(at, transform.forward, out targetHit);
        if (!raytrigger)
            return;

        float dis = Vector3.Distance(targetHit.point, transform.position);
        Debug.DrawRay(at, transform.forward * dis, Color.blue);

        Debug.DrawRay(flower.position + flower.forward * 0.05f, flower.forward, Color.blue); // 绘制每根轴
        Debug.DrawRay(flower.position + flower.forward * 0.05f, flower.right, Color.red);
        Debug.DrawRay(flower.position + flower.forward * 0.05f, flower.up, Color.green);
        
        Quaternion normal = Quaternion.LookRotation( targetHit.normal); //打到墙上的射线旋转

        Vector3 myforward = transform.forward; //镜头的方向,这里的贴花是根据第一人称武器挥舞作为参考方向的.

        //计算投影向量
        Vector3 rot = Vector3.Cross(myforward, phyDir.forward);   //算垂直于镜头法线和攻击方向的向量

        phyDirChuizhi.transform.forward = rot;  //测试用来显示的
        Vector3 touyingV3 = Vector3.Cross(targetHit.normal, rot); // 向量phyDir到墙面的投影

        touying.transform.position = targetHit.point;   //测试用来显示的
        touying.transform.forward = touyingV3;


        Quaternion rot2 = Quaternion.LookRotation(touyingV3, targetHit.normal);   //得到一个墙面法线向上的投影方向的向量

        //因为这个物理攻击贴花是Z轴朝着碰撞墙面的法线方向,所以要把旋转Z到X , Z再旋转到Y才可以.
        Quaternion dirq = Quaternion.FromToRotation(Vector3.forward, Vector3.right);    
        Quaternion dirq2 = Quaternion.FromToRotation(Vector3.forward, Vector3.up);

        flower.transform.rotation = rot2 * dirq * dirq2; //最终的方向.
        flower.transform.position = targetHit.point;

        pic2.eulerAngles = rot2.eulerAngles;
        pic2.transform.position = targetHit.point;
    }

    void OnGUI()
    {
        GUI.color = Color.black;
        Vector3 pt;
        pt = Camera.main.WorldToScreenPoint(flower.transform.position);
        GUI.Label(new Rect(pt.x, pt.y, 200, 50), "武器砍出来的贴花(最终效果)");

        pt = Camera.main.WorldToScreenPoint(phyDir.transform.position);
        GUI.Label(new Rect(pt.x, pt.y, 200, 50), "武器砍出来物理方向");

        pt = Camera.main.WorldToScreenPoint(phyDirChuizhi.transform.position);
        GUI.Label(new Rect(pt.x, pt.y, 200, 50), "垂直于物理方向的方向,用来计算投影向量");

        pt = Camera.main.WorldToScreenPoint(touying.transform.position+new Vector3(0f,0.2f,0f));
        GUI.Label(new Rect(pt.x, pt.y, 200, 50), "灰色长棍子是投影于平面的向量");
    }
}

放上几张图方便理解.
这个是Scene里的图,胶囊是玩家,大方盒子是墙,红色是地面,相机面前的白条子是武器挥舞后的力方向

这里写图片描述
这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thinbug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值