Собственно, сам скрипт:
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;
public class BulletMove : MonoBehaviour {
public float TimeToDestruct = 10;
public bool RandomDamage = true;
public float Damage = 20;
public float minRandLimit = -5;
public float maxRandLimit = 5;
public bool DamageReduction = true;
public float StartPoinOfDamageReduction = 20;
public float FinalDamageInPercent = 20;
public int StartSpeed = 50;
Vector3 PreviousStep;
float StartTime, TimeStartDamageReduction;
float CurrentDamage;
void Awake ()
{
Invoke ("DestroyNow", TimeToDestruct);
rigidbody.velocity = transform.TransformDirection(Vector3.forward * StartSpeed);
PreviousStep = gameObject.transform.position;
StartTime = Time.time;
TimeStartDamageReduction = TimeToDestruct * StartPoinOfDamageReduction / 100.0f;
CurrentDamage = Damage;
if(RandomDamage)
CurrentDamage += Random.Range(minRandLimit, maxRandLimit);
}
void FixedUpdate()
{
Quaternion CurrentStep = gameObject.transform.rotation;
transform.LookAt (PreviousStep, transform.up);
RaycastHit[] Objects;
Ray ray = new Ray (transform.position, transform.forward);
float Distance = Vector3.Distance (PreviousStep, transform.position);
if (Distance == 0)
Distance = 1.0f;
Objects = Physics.RaycastAll (ray, Distance);
if (Objects.Length != 0)
{
SendDamage(Objects [Objects.Length - 1].transform.gameObject);
}
gameObject.transform.rotation = CurrentStep;
PreviousStep = gameObject.transform.position;
}
void DestroyNow ()
{
DestroyObject (gameObject);
}
void OnCollisionEnter(Collision hit)
{
SendDamage (hit.gameObject);
}
void SendDamage(GameObject Hit)
{
Hit.SendMessage ("ApplyDamage", CurrentDamage * GetDamageCoefficient(), SendMessageOptions.DontRequireReceiver);
Destroy(gameObject);
}
float GetDamageCoefficient()
{
float Value = 1.0f;
if (DamageReduction)
{
float CurrentTime = Time.time - StartTime;
Debug.Log ("CurrentTime: " + CurrentTime);
if (CurrentTime >= TimeStartDamageReduction)
{
Value = 1.0f - (1 - FinalDamageInPercent / 100) * ((CurrentTime - TimeStartDamageReduction) / (TimeToDestruct - TimeStartDamageReduction));
}
}
return Value;
}
}
using System.Collections;
public class BulletMove : MonoBehaviour {
public float TimeToDestruct = 10;
public bool RandomDamage = true;
public float Damage = 20;
public float minRandLimit = -5;
public float maxRandLimit = 5;
public bool DamageReduction = true;
public float StartPoinOfDamageReduction = 20;
public float FinalDamageInPercent = 20;
public int StartSpeed = 50;
Vector3 PreviousStep;
float StartTime, TimeStartDamageReduction;
float CurrentDamage;
void Awake ()
{
Invoke ("DestroyNow", TimeToDestruct);
rigidbody.velocity = transform.TransformDirection(Vector3.forward * StartSpeed);
PreviousStep = gameObject.transform.position;
StartTime = Time.time;
TimeStartDamageReduction = TimeToDestruct * StartPoinOfDamageReduction / 100.0f;
CurrentDamage = Damage;
if(RandomDamage)
CurrentDamage += Random.Range(minRandLimit, maxRandLimit);
}
void FixedUpdate()
{
Quaternion CurrentStep = gameObject.transform.rotation;
transform.LookAt (PreviousStep, transform.up);
RaycastHit[] Objects;
Ray ray = new Ray (transform.position, transform.forward);
float Distance = Vector3.Distance (PreviousStep, transform.position);
if (Distance == 0)
Distance = 1.0f;
Objects = Physics.RaycastAll (ray, Distance);
if (Objects.Length != 0)
{
SendDamage(Objects [Objects.Length - 1].transform.gameObject);
}
gameObject.transform.rotation = CurrentStep;
PreviousStep = gameObject.transform.position;
}
void DestroyNow ()
{
DestroyObject (gameObject);
}
void OnCollisionEnter(Collision hit)
{
SendDamage (hit.gameObject);
}
void SendDamage(GameObject Hit)
{
Hit.SendMessage ("ApplyDamage", CurrentDamage * GetDamageCoefficient(), SendMessageOptions.DontRequireReceiver);
Destroy(gameObject);
}
float GetDamageCoefficient()
{
float Value = 1.0f;
if (DamageReduction)
{
float CurrentTime = Time.time - StartTime;
Debug.Log ("CurrentTime: " + CurrentTime);
if (CurrentTime >= TimeStartDamageReduction)
{
Value = 1.0f - (1 - FinalDamageInPercent / 100) * ((CurrentTime - TimeStartDamageReduction) / (TimeToDestruct - TimeStartDamageReduction));
}
}
return Value;
}
}
Немного обновил его! Более гибкая настройка нанесения дамага в зависимости от пройденного расстояния с помощью AnimationCurve. Учтите, что если график покрутить вручную, он так и останется! И значения будут сниматься с того, что Вы наскрутили! Так же, этот скрипм можно расценить как небольшое пояснение работы AnimationCurve)
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;
public class BulletMove : MonoBehaviour {
public float TimeToDestruct = 10;
public bool RandomDamage = true;
public float Damage = 20;
public float minRandLimit = -5;
public float maxRandLimit = 5;
public bool DamageReduction = true;
public float StartPoinOfDamageReduction = 20;
public float FinalDamageInPercent = 20;
public AnimationCurve DamageReductionGraph;
public int StartSpeed = 50;
Vector3 PreviousStep;
float StartTime;
float CurrentDamage;
void Awake ()
{
Invoke ("DestroyNow", TimeToDestruct);
rigidbody.velocity = transform.TransformDirection(Vector3.forward * StartSpeed);
PreviousStep = gameObject.transform.position;
StartTime = Time.time;
CurrentDamage = Damage;
if(RandomDamage)
CurrentDamage += Random.Range(minRandLimit, maxRandLimit);
Keyframe[] ks;
ks = new Keyframe [3];
ks [0] = new Keyframe (0, 1);
ks [1] = new Keyframe (StartPoinOfDamageReduction / 100, 1);
ks [2] = new Keyframe (1, FinalDamageInPercent / 100);
DamageReductionGraph = new AnimationCurve (ks);
}
void FixedUpdate()
{
Quaternion CurrentStep = gameObject.transform.rotation;
transform.LookAt (PreviousStep, transform.up);
RaycastHit[] Objects;
Ray ray = new Ray (transform.position, transform.forward);
float Distance = Vector3.Distance (PreviousStep, transform.position);
if (Distance == 0)
Distance = 1.0f;
Objects = Physics.RaycastAll (ray, Distance);
if (Objects.Length != 0)
{
SendDamage(Objects [Objects.Length - 1].transform.gameObject);
}
gameObject.transform.rotation = CurrentStep;
PreviousStep = gameObject.transform.position;
}
void DestroyNow ()
{
DestroyObject (gameObject);
}
void OnCollisionEnter(Collision hit)
{
SendDamage (hit.gameObject);
}
void SendDamage(GameObject Hit)
{
Hit.SendMessage ("ApplyDamage", CurrentDamage * GetDamageCoefficient(), SendMessageOptions.DontRequireReceiver);
Destroy(gameObject);
}
float GetDamageCoefficient()
{
float Value = 1.0f;
float CurrentTime = Time.time - StartTime;
Value = DamageReductionGraph.Evaluate(CurrentTime / TimeToDestruct);
return Value;
}
}
using System.Collections;
public class BulletMove : MonoBehaviour {
public float TimeToDestruct = 10;
public bool RandomDamage = true;
public float Damage = 20;
public float minRandLimit = -5;
public float maxRandLimit = 5;
public bool DamageReduction = true;
public float StartPoinOfDamageReduction = 20;
public float FinalDamageInPercent = 20;
public AnimationCurve DamageReductionGraph;
public int StartSpeed = 50;
Vector3 PreviousStep;
float StartTime;
float CurrentDamage;
void Awake ()
{
Invoke ("DestroyNow", TimeToDestruct);
rigidbody.velocity = transform.TransformDirection(Vector3.forward * StartSpeed);
PreviousStep = gameObject.transform.position;
StartTime = Time.time;
CurrentDamage = Damage;
if(RandomDamage)
CurrentDamage += Random.Range(minRandLimit, maxRandLimit);
Keyframe[] ks;
ks = new Keyframe [3];
ks [0] = new Keyframe (0, 1);
ks [1] = new Keyframe (StartPoinOfDamageReduction / 100, 1);
ks [2] = new Keyframe (1, FinalDamageInPercent / 100);
DamageReductionGraph = new AnimationCurve (ks);
}
void FixedUpdate()
{
Quaternion CurrentStep = gameObject.transform.rotation;
transform.LookAt (PreviousStep, transform.up);
RaycastHit[] Objects;
Ray ray = new Ray (transform.position, transform.forward);
float Distance = Vector3.Distance (PreviousStep, transform.position);
if (Distance == 0)
Distance = 1.0f;
Objects = Physics.RaycastAll (ray, Distance);
if (Objects.Length != 0)
{
SendDamage(Objects [Objects.Length - 1].transform.gameObject);
}
gameObject.transform.rotation = CurrentStep;
PreviousStep = gameObject.transform.position;
}
void DestroyNow ()
{
DestroyObject (gameObject);
}
void OnCollisionEnter(Collision hit)
{
SendDamage (hit.gameObject);
}
void SendDamage(GameObject Hit)
{
Hit.SendMessage ("ApplyDamage", CurrentDamage * GetDamageCoefficient(), SendMessageOptions.DontRequireReceiver);
Destroy(gameObject);
}
float GetDamageCoefficient()
{
float Value = 1.0f;
float CurrentTime = Time.time - StartTime;
Value = DamageReductionGraph.Evaluate(CurrentTime / TimeToDestruct);
return Value;
}
}
UPDATE!
И вот, пока третий, но, вроде, не финальный релиз скрипта. Траблы с нанесением двойного урона исключены. Данный скрипт вешается на пустой!(если будут меши или коллайдеры, пуля самоуничтожится! В предыдущих скриптах такого не было, так как мы стреляли в обратную сторону) GameObject с RigidBody. Гораздо менее нагружает игру. Позволяет в поле "Particle Hit" добавить эффект попадания. Тестилось на скоростях от 1 до 500к единиц. Всё работало отлично. Можете использовать.
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;
public class BulletMove : MonoBehaviour {
public float TimeToDestruct = 10;
public bool RandomDamage = true;
public float Damage = 20;
public float minRandLimit = -5;
public float maxRandLimit = 5;
public bool DamageReduction = true;
public float StartPoinOfDamageReduction = 20;
public float FinalDamageInPercent = 20;
public AnimationCurve DamageReductionGraph;
public int StartSpeed = 50;
public GameObject particleHit;
Vector3 PreviousStep;
float StartTime;
float CurrentDamage;
void Awake ()
{
Invoke ("DestroyNow", TimeToDestruct);
rigidbody.velocity = transform.TransformDirection(Vector3.forward * StartSpeed);
PreviousStep = gameObject.transform.position;
StartTime = Time.time;
CurrentDamage = Damage;
if(RandomDamage)
CurrentDamage += Random.Range(minRandLimit, maxRandLimit);
Keyframe[] ks;
ks = new Keyframe [3];
ks [0] = new Keyframe (0, 1);
ks [1] = new Keyframe (StartPoinOfDamageReduction / 100, 1);
ks [2] = new Keyframe (1, FinalDamageInPercent / 100);
DamageReductionGraph = new AnimationCurve (ks);
}
void FixedUpdate()
{
Quaternion CurrentStep = gameObject.transform.rotation;
transform.LookAt (PreviousStep, transform.up);
RaycastHit hit = new RaycastHit();
float Distance = Vector3.Distance (PreviousStep, transform.position);
if (Distance == 0.0f)
Distance = 1e-05f;
Debug.Log(Distance);
if(Physics.Raycast(PreviousStep, transform.TransformDirection(Vector3.back), out hit, Distance * 0.9999f) && (hit.transform.gameObject != gameObject))
{
Instantiate(particleHit, hit.point, Quaternion.FromToRotation(Vector3.up, hit.normal));
SendDamage(hit.transform.gameObject);
}
gameObject.transform.rotation = CurrentStep;
PreviousStep = gameObject.transform.position;
}
void DestroyNow ()
{
DestroyObject (gameObject);
}
void SendDamage(GameObject Hit)
{
Hit.SendMessage ("ApplyDamage", CurrentDamage * GetDamageCoefficient(), SendMessageOptions.DontRequireReceiver);
Destroy(gameObject);
}
float GetDamageCoefficient()
{
float Value = 1.0f;
float CurrentTime = Time.time - StartTime;
Value = DamageReductionGraph.Evaluate(CurrentTime / TimeToDestruct);
return Value;
}
}
using System.Collections;
public class BulletMove : MonoBehaviour {
public float TimeToDestruct = 10;
public bool RandomDamage = true;
public float Damage = 20;
public float minRandLimit = -5;
public float maxRandLimit = 5;
public bool DamageReduction = true;
public float StartPoinOfDamageReduction = 20;
public float FinalDamageInPercent = 20;
public AnimationCurve DamageReductionGraph;
public int StartSpeed = 50;
public GameObject particleHit;
Vector3 PreviousStep;
float StartTime;
float CurrentDamage;
void Awake ()
{
Invoke ("DestroyNow", TimeToDestruct);
rigidbody.velocity = transform.TransformDirection(Vector3.forward * StartSpeed);
PreviousStep = gameObject.transform.position;
StartTime = Time.time;
CurrentDamage = Damage;
if(RandomDamage)
CurrentDamage += Random.Range(minRandLimit, maxRandLimit);
Keyframe[] ks;
ks = new Keyframe [3];
ks [0] = new Keyframe (0, 1);
ks [1] = new Keyframe (StartPoinOfDamageReduction / 100, 1);
ks [2] = new Keyframe (1, FinalDamageInPercent / 100);
DamageReductionGraph = new AnimationCurve (ks);
}
void FixedUpdate()
{
Quaternion CurrentStep = gameObject.transform.rotation;
transform.LookAt (PreviousStep, transform.up);
RaycastHit hit = new RaycastHit();
float Distance = Vector3.Distance (PreviousStep, transform.position);
if (Distance == 0.0f)
Distance = 1e-05f;
Debug.Log(Distance);
if(Physics.Raycast(PreviousStep, transform.TransformDirection(Vector3.back), out hit, Distance * 0.9999f) && (hit.transform.gameObject != gameObject))
{
Instantiate(particleHit, hit.point, Quaternion.FromToRotation(Vector3.up, hit.normal));
SendDamage(hit.transform.gameObject);
}
gameObject.transform.rotation = CurrentStep;
PreviousStep = gameObject.transform.position;
}
void DestroyNow ()
{
DestroyObject (gameObject);
}
void SendDamage(GameObject Hit)
{
Hit.SendMessage ("ApplyDamage", CurrentDamage * GetDamageCoefficient(), SendMessageOptions.DontRequireReceiver);
Destroy(gameObject);
}
float GetDamageCoefficient()
{
float Value = 1.0f;
float CurrentTime = Time.time - StartTime;
Value = DamageReductionGraph.Evaluate(CurrentTime / TimeToDestruct);
return Value;
}
}
P.S. Просьба старые варианты не удалять, вдруг кому пригодится. А места он не много занимает.
Вся критика приветствуется. Благодарю за внимание!