Demo截图:
我写得不是很好,如果各位大鸟有更好的思路,可以分享给我研究研究
using UnityEngine;
using System.Collections;
public delegate void AttackStateDelegate(string name);
public class PlayerAttackController : MonoBehaviour {
//派发改变攻击动画状态的委托
public AttackStateDelegate setAttackState = null;
//记录当前攻击动画;
AnimationClip currentAttack;
//获取人物动画组件;
Animation playerAnimation;
//动画标签;
public enum ActionState
{
Attack_0,
Attack_1,
Attack_2,
Attack_3,
None
}
//记录当前动画标签;
private ActionState actionState = ActionState.None;
/**
* 攻击的逻辑
*/
void AttackLogic(){
if (Input.GetButtonDown("Fire1")){
if (actionState != ActionState.Attack_0 && actionState != ActionState.Attack_1&& actionState != ActionState.Attack_2&& actionState != ActionState.Attack_3) {
actionState = ActionState.Attack_0;
}else if (actionState == ActionState.Attack_0 && playerAnimation[currentAttack.name].time > 1.0f){
actionState = ActionState.Attack_1;
}else if (actionState == ActionState.Attack_1 && playerAnimation[currentAttack.name].time > 1.3f){
actionState = ActionState.Attack_2;
}else if (actionState == ActionState.Attack_2 && playerAnimation[currentAttack.name].time > 0.45f){
actionState = ActionState.Attack_3;
}
}
}
/**
* 攻击套路选择
*/
void Attacks (){
float delayTime =0.0f;
switch (actionState){
case ActionState.Attack_0:
delayTime = -0.1f;
if(setAttackState!=null){
setAttackState("Attack");
}
playerAnimation.CrossFade("Attack", 0.15f);
currentAttack = playerAnimation["Attack"].clip;
break;
case ActionState.Attack_1:
delayTime = -0.1f;
if(setAttackState!=null){
setAttackState("Attack01");
}
playerAnimation.CrossFade("Attack01", 0.15f);
currentAttack = playerAnimation["Attack01"].clip;
break;
case ActionState.Attack_2:
delayTime = -0.1f;
if(setAttackState!=null){
setAttackState("Attack02");
}
playerAnimation.CrossFade("Attack02", 0.05f);
currentAttack = playerAnimation["Attack02"].clip;
break;
case ActionState.Attack_3:
delayTime = -0.1f;
if(setAttackState!=null){
setAttackState("Attack03");
}
playerAnimation.CrossFade("Attack03", 0.15f);
currentAttack = playerAnimation["Attack03"].clip;
break;
case ActionState.None:
if(setAttackState!=null){
setAttackState("None");
}
break;
}
//Switch to default if an animation is almost over
if (playerAnimation[currentAttack.name].time > (playerAnimation[currentAttack.name].length +delayTime)){
actionState = ActionState.None;
currentAttack = playerAnimation["AttackStandy"].clip;
playerAnimation.CrossFade("AttackStandy", 0.5f);
}
}
void Awake(){
//程序开启前,获取人物动画组件;
playerAnimation = GetComponent () as Animation;
playerAnimation["Attack"].speed=1.6f;
playerAnimation["Attack01"].speed=1.3f;
playerAnimation["Attack02"].speed=1.2f;
playerAnimation["Attack03"].speed=1.5f;
}
protected void Initialise (){
}
void Start () {
if (playerAnimation.clip) {
currentAttack = playerAnimation.clip;
} else {
currentAttack = playerAnimation["AttackStandy"].clip;
}
}
// Update is called once per frame
void Update () {
if (currentAttack != null){
AttackLogic();
Attacks();
}
}
}
using UnityEngine;
using System.Collections;
/**
*所有player事件统一处理的单例事例;
*
*/
public class PlayerDelegate : MonoBehaviour {
//攻击脚本;
PlayerAttackController playerAc;
//刀的轨迹脚本;
SwordTrial swordTrial;
// Use this for initialization
void Start () {
swordTrial = GetComponent() as SwordTrial;
playerAc = GetComponent() as PlayerAttackController;
playerAc.setAttackState +=setAttackState;
}
void setAttackState(string str){
swordTrial.setAttackState(str);
}
// Update is called once per frame
void Update () {
}
}
using UnityEngine;
using System.Collections;
public class SwordTrial : MonoBehaviour {
//MeleeTrailSample
public MeleeWeaponTrail _trail;
//记录当前动画Clip;
public AnimationState _animationState;
//记录当前动画帧数;
float currentFrame =0.0f;
//开始动画帧数;
float startTime = 0.0f;
//结束动画帧数;
float endTime = 0.0f;
//记录攻击状态;
private string actionState="None";
void Start () {
//初始化trail不可见;
_trail.Emit = false;
}
/**
* 外部调用改变攻击状态;
*/
public void setAttackState(string str){
actionState = str;
_animationState = animation[actionState];
}
// Update is called once per frame
void Update () {
if(actionState!="None"){
if(animation.IsPlaying(actionState)){
if(actionState=="Attack"){
startTime = 0.72f;
endTime = 0.85f;
}else if(actionState=="Attack01"){
startTime = 0.95f;
endTime = 1.5f;
}else if(actionState=="Attack02"){
startTime =0.05f;
endTime = 1.2f;
}else if(actionState=="Attack03"){
startTime =0.45f;
endTime = 0.58f;
}
currentFrame=_animationState.normalizedTime*_animationState.clip.length;
if(currentFrame>=startTime&¤tFrame<=endTime){
_trail.Emit = true;
}else{
_trail.Emit = false;
}
}
}else{
_trail.Emit = false;
}
}
}
#define USE_INTERPOLATION
//
// By Anomalous Underdog, 2011
//
// Based on code made by Forest Johnson (Yoggy) and xyber
//
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MeleeWeaponTrail : MonoBehaviour
{
[SerializeField]
bool _emit = true;
public bool Emit { set{_emit = value;} }
bool _use = true;
public bool Use { set{_use = value;} }
[SerializeField]
float _emitTime = 0.0f;
[SerializeField]
Material _material;
[SerializeField]
float _lifeTime = 1.0f;
[SerializeField]
Color[] _colors;
[SerializeField]
float[] _sizes;
[SerializeField]
float _minVertexDistance = 0.1f;
[SerializeField]
float _maxVertexDistance = 10.0f;
float _minVertexDistanceSqr = 0.0f;
float _maxVertexDistanceSqr = 0.0f;
[SerializeField]
float _maxAngle = 3.00f;
[SerializeField]
bool _autoDestruct = false;
#if USE_INTERPOLATION
[SerializeField]
int subdivisions = 4;
#endif
[SerializeField]
Transform _base;
[SerializeField]
Transform _tip;
List _points = new List();
#if USE_INTERPOLATION
List _smoothedPoints = new List();
#endif
GameObject _trailObject;
Mesh _trailMesh;
Vector3 _lastPosition;
[System.Serializable]
public class Point
{
public float timeCreated = 0.0f;
public Vector3 basePosition;
public Vector3 tipPosition;
}
void Start()
{
_lastPosition = transform.position;
_trailObject = new GameObject("Trail");
_trailObject.transform.parent = null;
_trailObject.transform.position = Vector3.zero;
_trailObject.transform.rotation = Quaternion.identity;
_trailObject.transform.localScale = Vector3.one;
_trailObject.AddComponent(typeof(MeshFilter));
_trailObject.AddComponent(typeof(MeshRenderer));
_trailObject.renderer.material = _material;
_trailMesh = new Mesh();
_trailMesh.name = name + "TrailMesh";
_trailObject.GetComponent().mesh = _trailMesh;
_minVertexDistanceSqr = _minVertexDistance * _minVertexDistance;
_maxVertexDistanceSqr = _maxVertexDistance * _maxVertexDistance;
}
void OnDisable()
{
Destroy(_trailObject);
}
void Update()
{
if (!_use)
{
return;
}
if (_emit && _emitTime != 0)
{
_emitTime -= Time.deltaTime;
if (_emitTime == 0) _emitTime = -1;
if (_emitTime < 0) _emit = false;
}
if (_emit==false && _points.Count == 0 && _autoDestruct)
{
Destroy(_trailObject);
Destroy(gameObject);
}
// early out if there is no camera
if (!Camera.main) return;
// if we have moved enough, create a new vertex and make sure we rebuild the mesh
float theDistanceSqr = (_lastPosition - transform.position).sqrMagnitude;
if (_emit)
{
if (theDistanceSqr > _minVertexDistanceSqr)
{
bool make = false;
if (_points.Count < 3)
{
make = true;
}
else
{
//Vector3 l1 = _points[_points.Count - 2].basePosition - _points[_points.Count - 3].basePosition;
//Vector3 l2 = _points[_points.Count - 1].basePosition - _points[_points.Count - 2].basePosition;
Vector3 l1 = _points[_points.Count - 2].tipPosition - _points[_points.Count - 3].tipPosition;
Vector3 l2 = _points[_points.Count - 1].tipPosition - _points[_points.Count - 2].tipPosition;
if (Vector3.Angle(l1, l2) > _maxAngle || theDistanceSqr > _maxVertexDistanceSqr) make = true;
}
if (make)
{
Point p = new Point();
p.basePosition = _base.position;
p.tipPosition = _tip.position;
p.timeCreated = Time.time;
_points.Add(p);
_lastPosition = transform.position;
#if USE_INTERPOLATION
if (_points.Count == 1)
{
_smoothedPoints.Add(p);
}
else if (_points.Count > 1)
{
// add 1+subdivisions for every possible pair in the _points
for (int n = 0; n < 1+subdivisions; ++n)
_smoothedPoints.Add(p);
}
// we use 4 control points for the smoothing
if (_points.Count >= 4)
{
Vector3[] tipPoints = new Vector3[4];
tipPoints[0] = _points[_points.Count - 4].tipPosition;
tipPoints[1] = _points[_points.Count - 3].tipPosition;
tipPoints[2] = _points[_points.Count - 2].tipPosition;
tipPoints[3] = _points[_points.Count - 1].tipPosition;
//IEnumerable smoothTip = Interpolate.NewBezier(Interpolate.Ease(Interpolate.EaseType.Linear), tipPoints, subdivisions);
IEnumerable smoothTip = Interpolate.NewCatmullRom(tipPoints, subdivisions, false);
Vector3[] basePoints = new Vector3[4];
basePoints[0] = _points[_points.Count - 4].basePosition;
basePoints[1] = _points[_points.Count - 3].basePosition;
basePoints[2] = _points[_points.Count - 2].basePosition;
basePoints[3] = _points[_points.Count - 1].basePosition;
//IEnumerable smoothBase = Interpolate.NewBezier(Interpolate.Ease(Interpolate.EaseType.Linear), basePoints, subdivisions);
IEnumerable smoothBase = Interpolate.NewCatmullRom(basePoints, subdivisions, false);
List smoothTipList = new List(smoothTip);
List smoothBaseList = new List(smoothBase);
float firstTime = _points[_points.Count - 4].timeCreated;
float secondTime = _points[_points.Count - 1].timeCreated;
//Debug.Log(" smoothTipList.Count: " + smoothTipList.Count);
for (int n = 0; n < smoothTipList.Count; ++n)
{
int idx = _smoothedPoints.Count - (smoothTipList.Count-n);
// there are moments when the _smoothedPoints are lesser
// than what is required, when elements from it are removed
if (idx > -1 && idx < _smoothedPoints.Count)
{
Point sp = new Point();
sp.basePosition = smoothBaseList[n];
sp.tipPosition = smoothTipList[n];
sp.timeCreated = Mathf.Lerp(firstTime, secondTime, (float)n/smoothTipList.Count);
_smoothedPoints[idx] = sp;
}
//else
//{
// Debug.LogError(idx + "/" + _smoothedPoints.Count);
//}
}
}
#endif
}
else
{
_points[_points.Count - 1].basePosition = _base.position;
_points[_points.Count - 1].tipPosition = _tip.position;
//_points[_points.Count - 1].timeCreated = Time.time;
#if USE_INTERPOLATION
_smoothedPoints[_smoothedPoints.Count - 1].basePosition = _base.position;
_smoothedPoints[_smoothedPoints.Count - 1].tipPosition = _tip.position;
#endif
}
}
else
{
if (_points.Count > 0)
{
_points[_points.Count - 1].basePosition = _base.position;
_points[_points.Count - 1].tipPosition = _tip.position;
//_points[_points.Count - 1].timeCreated = Time.time;
}
#if USE_INTERPOLATION
if (_smoothedPoints.Count > 0)
{
_smoothedPoints[_smoothedPoints.Count - 1].basePosition = _base.position;
_smoothedPoints[_smoothedPoints.Count - 1].tipPosition = _tip.position;
}
#endif
}
}
RemoveOldPoints(_points);
if (_points.Count == 0)
{
_trailMesh.Clear();
}
#if USE_INTERPOLATION
RemoveOldPoints(_smoothedPoints);
if (_smoothedPoints.Count == 0)
{
_trailMesh.Clear();
}
#endif
#if USE_INTERPOLATION
List pointsToUse = _smoothedPoints;
#else
List pointsToUse = _points;
#endif
if (pointsToUse.Count > 1)
{
Vector3[] newVertices = new Vector3[pointsToUse.Count * 2];
Vector2[] newUV = new Vector2[pointsToUse.Count * 2];
int[] newTriangles = new int[(pointsToUse.Count - 1) * 6];
Color[] newColors = new Color[pointsToUse.Count * 2];
for (int n = 0; n < pointsToUse.Count; ++n)
{
Point p = pointsToUse[n];
float time = (Time.time - p.timeCreated) / _lifeTime;
Color color = Color.Lerp(Color.white, Color.clear, time);
if (_colors != null && _colors.Length > 0)
{
float colorTime = time * (_colors.Length - 1);
float min = Mathf.Floor(colorTime);
float max = Mathf.Clamp(Mathf.Ceil(colorTime), 1, _colors.Length - 1);
float lerp = Mathf.InverseLerp(min, max, colorTime);
if (min >= _colors.Length) min = _colors.Length - 1; if (min < 0) min = 0;
if (max >= _colors.Length) max = _colors.Length - 1; if (max < 0) max = 0;
color = Color.Lerp(_colors[(int)min], _colors[(int)max], lerp);
}
float size = 0f;
if (_sizes != null && _sizes.Length > 0)
{
float sizeTime = time * (_sizes.Length - 1);
float min = Mathf.Floor(sizeTime);
float max = Mathf.Clamp(Mathf.Ceil(sizeTime), 1, _sizes.Length - 1);
float lerp = Mathf.InverseLerp(min, max, sizeTime);
if (min >= _sizes.Length) min = _sizes.Length - 1; if (min < 0) min = 0;
if (max >= _sizes.Length) max = _sizes.Length - 1; if (max < 0) max = 0;
size = Mathf.Lerp(_sizes[(int)min], _sizes[(int)max], lerp);
}
Vector3 lineDirection = p.tipPosition - p.basePosition;
newVertices[n * 2] = p.basePosition - (lineDirection * (size * 0.5f));
newVertices[(n * 2) + 1] = p.tipPosition + (lineDirection * (size * 0.5f));
newColors[n * 2] = newColors[(n * 2) + 1] = color;
float uvRatio = (float)n/pointsToUse.Count;
newUV[n * 2] = new Vector2(uvRatio, 0);
newUV[(n * 2) + 1] = new Vector2(uvRatio, 1);
if (n > 0)
{
newTriangles[(n - 1) * 6] = (n * 2) - 2;
newTriangles[((n - 1) * 6) + 1] = (n * 2) - 1;
newTriangles[((n - 1) * 6) + 2] = n * 2;
newTriangles[((n - 1) * 6) + 3] = (n * 2) + 1;
newTriangles[((n - 1) * 6) + 4] = n * 2;
newTriangles[((n - 1) * 6) + 5] = (n * 2) - 1;
}
}
_trailMesh.Clear();
_trailMesh.vertices = newVertices;
_trailMesh.colors = newColors;
_trailMesh.uv = newUV;
_trailMesh.triangles = newTriangles;
}
}
void RemoveOldPoints(List pointList)
{
List remove = new List();
foreach (Point p in pointList)
{
// cull old points first
if (Time.time - p.timeCreated > _lifeTime)
{
remove.Add(p);
}
}
foreach (Point p in remove)
{
pointList.Remove(p);
}
}
}
QQ图片20131029141124.jpg(42 Bytes, 下载次数: 0)
QQ图片20131029141147.jpg(73 Bytes, 下载次数: 0)