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,黄色的类似长方形我们假定是攻击的特效.图中的蓝色,绿色,红色线是代码里绘制的,代表了他的坐标轴.
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), "灰色长棍子是投影于平面的向量");
}
}
放上几张图方便理解.