Простая замена встроеному Wheel Collider. Колесо скриптом. - Форум Игроделов
Чт, 18 Апр 2024, 20:55 
 
Приветствую Вас Гость Главная | Регистрация | Вход
Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум Игроделов » UNITY3D » ТРАНСПОРТ » Простая замена встроеному Wheel Collider. Колесо скриптом. (Скрипт JS + box collider.)
Простая замена встроеному Wheel Collider. Колесо скриптом.
VolkOrievithДата: Ср, 22 Июн 2016, 22:14 | Сообщение # 1
Нет аватара
 
Сообщений: 222
Награды: 0
Репутация: 53
Статус: Offline
Скрипт работал бы на любой версии Unity, если б не "Vector3.ProjectOnPlane". Эта функция есть только в пятой юне. "Vector3.Project" работает как-то иначе.
Кидать прямо на колесо. Реализовано Raycast'ом.


Особенность:


Желательно назначить колесу любой Сollider и настроить, условие Center.y * 2 = Size.y, чтобы нижня сторона коллайдера была посредине колеса. Без него вполне возможно, что при падении колесо провалится сквозь землю.

Демо (яндекс диск): Демо 36мб.
(только что, 24.06, обновил демку. Была шестиколесная телега, сейчас авто из Car Tutorial)

Вот, собственно, сам скрипт:
Код
#pragma strict
//////////////////////////////////Script "Wheel" by VolkOrievith///////////////////////////////
@HeaderAttribute("Wheel setup")
var WheelMesh : Transform;
var Radius : float = 0.3;
var ForceApPointDistance : float;
var SuspensionDistance : float = 0.3;
var FixedSpeed : boolean; //переключатель контроля. Либо через Speed, либо через AddForce.
var BeakForce : float;
var Speed : float;
var AddForce : float;
var MuvingPlatform : LayerMask;
@Space(8)
var RPM : float;

@Space(15)
@HeaderAttribute("Suspension")

var Spring : float = 5000;
var Dumper : float = 500;

@Space(15)
@HeaderAttribute("Friction")
var StaticFriction : float;  
var SlidingFriction : float;
@Space(5)
var StaticForce : float = 2000f;
var SlidingForce : float = 800f;
@Space(5)
var MaxStaticForce : float = 1500f;
var MinSlidingForce : float = 800f;
@Space(5)
var Sliding : boolean;

private var LastDist : float;
private var LastPoint : Vector3;
private var LastTRDPoint : Vector3;
private var LastTRDO : Transform;
private var RB : Rigidbody;

function Start () {
RB = GetComponentInParent.<Rigidbody>();
LastPoint = transform.position;
}
private var Vel : Vector3;
function FixedUpdate () {
Vel = Vector3.zero;

var wh : RaycastHit;
//Debug.DrawLine (transform.position,transform.position - transform.up * SuspensionDistance);
if ( Physics.Raycast ( transform.position + transform.up*0.1, -transform.up, wh, SuspensionDistance+0.1, MuvingPlatform)){
if (WheelMesh)
WheelMesh.position = wh.point + transform.up * (Radius);

var SD = Mathf.Clamp( (-(wh.distance-0.1) + SuspensionDistance) / SuspensionDistance, 0.001, 5.0);
var Force = wh.normal * Mathf.Clamp( Spring * Mathf.Pow(SD, .8) + Dumper * (LastDist - wh.distance) / Time.fixedDeltaTime / SuspensionDistance, 0, Mathf.Infinity);
RB.AddForceAtPosition ( Force, transform.position);
//Debug.Log (SD + " = " + Mathf.Pow(SD, .8));
//Debug.Log ("(" + LastDist[0] + " - " + wh[0].distance + ") / Time.fixedDeltaTime / " + SuspensionDistance + " * " + Dumper + " = " + (LastDist[0] - wh[0].distance) / Time.fixedDeltaTime / SuspensionDistance * Dumper);

Vel = (transform.position - LastPoint) / Time.fixedDeltaTime;
if (LastTRDPoint != Vector3.zero && LastTRDO == wh.collider.transform)
Vel = wh.collider.transform.TransformDirection(wh.collider.transform.InverseTransformDirection(transform.position - wh.collider.transform.position) - LastTRDPoint) / Time.fixedDeltaTime;

var FForce = -(Vector3.down * RB.mass * 9.81 + Force)/4;
RPM = Speed * Radius * 60;
if (FixedSpeed){
if ( Sliding)
Speed = Mathf.MoveTowards ( transform.InverseTransformDirection (Vel).z - (transform.InverseTransformDirection (FForce*0.9).z-AddForce / SlidingFriction)/RB.mass/4, 0, BeakForce*Time.fixedDeltaTime);
else
Speed = Mathf.MoveTowards ( transform.InverseTransformDirection (Vel).z - (transform.InverseTransformDirection (FForce*0.9).z-AddForce / StaticFriction)/RB.mass/4, 0, BeakForce*Time.fixedDeltaTime);
}
FForce = Vector3.ProjectOnPlane(FForce, wh.normal);
Vel -= transform.forward * Speed;
if ( !Sliding && (Vel * StaticForce).magnitude > MaxStaticForce){
Sliding = true;
}
if ( Sliding && (Vel * SlidingForce).magnitude < MinSlidingForce){
Sliding = false;
}
//Debug.DrawLine (transform.position,transform.position+FForce/3000, Color.yellow);

LastDist = wh.distance;
LastTRDPoint = wh.collider.transform.InverseTransformDirection(transform.position - wh.collider.transform.position);
LastTRDO = wh.collider.transform;

if ( Marks && Sliding){
LastSKM = Skidmarks.AddSkidMark ( wh.point + Vel * Time.fixedDeltaTime, wh.normal, Vel.magnitude / 10, LastSKM);
}else
LastSKM = -1;

}else{
LastTRDPoint = Vector3.zero;
if (WheelMesh)
WheelMesh.position = transform.position + transform.up*(Radius - SuspensionDistance);
LastDist = SuspensionDistance;
if (FixedSpeed)
Speed = (Speed + AddForce*Time.fixedDeltaTime/RB.mass)/(1+BeakForce*Time.fixedDeltaTime);
RPM = Speed * Radius * 60;

LastSKM = -1;
}
LastPoint = transform.position;
if ( !Sliding){
RB.AddForceAtPosition ( FForce * StaticFriction - Vel * StaticForce, wh.point + transform.up*ForceApPointDistance);
}else{
if ( Vel.magnitude > MaxStaticForce)
Vel = Vel.normalized*MaxStaticForce;
RB.AddForceAtPosition ( FForce * SlidingFriction - Vel * SlidingForce, wh.point + transform.up*ForceApPointDistance);
}
if (WheelMesh)
WheelMesh.RotateAround ( transform.right, RPM * 90 / 60 / Radius * Time.fixedDeltaTime * Mathf.Deg2Rad);

}


З.Ы:
Обновил скрипт, изменил принцип торможения BrakeForce.


Сообщение отредактировал VolkOrievith - Пт, 24 Июн 2016, 16:05
 
СообщениеСкрипт работал бы на любой версии Unity, если б не "Vector3.ProjectOnPlane". Эта функция есть только в пятой юне. "Vector3.Project" работает как-то иначе.
Кидать прямо на колесо. Реализовано Raycast'ом.


Особенность:


Желательно назначить колесу любой Сollider и настроить, условие Center.y * 2 = Size.y, чтобы нижня сторона коллайдера была посредине колеса. Без него вполне возможно, что при падении колесо провалится сквозь землю.

Демо (яндекс диск): Демо 36мб.
(только что, 24.06, обновил демку. Была шестиколесная телега, сейчас авто из Car Tutorial)

Вот, собственно, сам скрипт:
Код
#pragma strict
//////////////////////////////////Script "Wheel" by VolkOrievith///////////////////////////////
@HeaderAttribute("Wheel setup")
var WheelMesh : Transform;
var Radius : float = 0.3;
var ForceApPointDistance : float;
var SuspensionDistance : float = 0.3;
var FixedSpeed : boolean; //переключатель контроля. Либо через Speed, либо через AddForce.
var BeakForce : float;
var Speed : float;
var AddForce : float;
var MuvingPlatform : LayerMask;
@Space(8)
var RPM : float;

@Space(15)
@HeaderAttribute("Suspension")

var Spring : float = 5000;
var Dumper : float = 500;

@Space(15)
@HeaderAttribute("Friction")
var StaticFriction : float;  
var SlidingFriction : float;
@Space(5)
var StaticForce : float = 2000f;
var SlidingForce : float = 800f;
@Space(5)
var MaxStaticForce : float = 1500f;
var MinSlidingForce : float = 800f;
@Space(5)
var Sliding : boolean;

private var LastDist : float;
private var LastPoint : Vector3;
private var LastTRDPoint : Vector3;
private var LastTRDO : Transform;
private var RB : Rigidbody;

function Start () {
RB = GetComponentInParent.<Rigidbody>();
LastPoint = transform.position;
}
private var Vel : Vector3;
function FixedUpdate () {
Vel = Vector3.zero;

var wh : RaycastHit;
//Debug.DrawLine (transform.position,transform.position - transform.up * SuspensionDistance);
if ( Physics.Raycast ( transform.position + transform.up*0.1, -transform.up, wh, SuspensionDistance+0.1, MuvingPlatform)){
if (WheelMesh)
WheelMesh.position = wh.point + transform.up * (Radius);

var SD = Mathf.Clamp( (-(wh.distance-0.1) + SuspensionDistance) / SuspensionDistance, 0.001, 5.0);
var Force = wh.normal * Mathf.Clamp( Spring * Mathf.Pow(SD, .8) + Dumper * (LastDist - wh.distance) / Time.fixedDeltaTime / SuspensionDistance, 0, Mathf.Infinity);
RB.AddForceAtPosition ( Force, transform.position);
//Debug.Log (SD + " = " + Mathf.Pow(SD, .8));
//Debug.Log ("(" + LastDist[0] + " - " + wh[0].distance + ") / Time.fixedDeltaTime / " + SuspensionDistance + " * " + Dumper + " = " + (LastDist[0] - wh[0].distance) / Time.fixedDeltaTime / SuspensionDistance * Dumper);

Vel = (transform.position - LastPoint) / Time.fixedDeltaTime;
if (LastTRDPoint != Vector3.zero && LastTRDO == wh.collider.transform)
Vel = wh.collider.transform.TransformDirection(wh.collider.transform.InverseTransformDirection(transform.position - wh.collider.transform.position) - LastTRDPoint) / Time.fixedDeltaTime;

var FForce = -(Vector3.down * RB.mass * 9.81 + Force)/4;
RPM = Speed * Radius * 60;
if (FixedSpeed){
if ( Sliding)
Speed = Mathf.MoveTowards ( transform.InverseTransformDirection (Vel).z - (transform.InverseTransformDirection (FForce*0.9).z-AddForce / SlidingFriction)/RB.mass/4, 0, BeakForce*Time.fixedDeltaTime);
else
Speed = Mathf.MoveTowards ( transform.InverseTransformDirection (Vel).z - (transform.InverseTransformDirection (FForce*0.9).z-AddForce / StaticFriction)/RB.mass/4, 0, BeakForce*Time.fixedDeltaTime);
}
FForce = Vector3.ProjectOnPlane(FForce, wh.normal);
Vel -= transform.forward * Speed;
if ( !Sliding && (Vel * StaticForce).magnitude > MaxStaticForce){
Sliding = true;
}
if ( Sliding && (Vel * SlidingForce).magnitude < MinSlidingForce){
Sliding = false;
}
//Debug.DrawLine (transform.position,transform.position+FForce/3000, Color.yellow);

LastDist = wh.distance;
LastTRDPoint = wh.collider.transform.InverseTransformDirection(transform.position - wh.collider.transform.position);
LastTRDO = wh.collider.transform;

if ( Marks && Sliding){
LastSKM = Skidmarks.AddSkidMark ( wh.point + Vel * Time.fixedDeltaTime, wh.normal, Vel.magnitude / 10, LastSKM);
}else
LastSKM = -1;

}else{
LastTRDPoint = Vector3.zero;
if (WheelMesh)
WheelMesh.position = transform.position + transform.up*(Radius - SuspensionDistance);
LastDist = SuspensionDistance;
if (FixedSpeed)
Speed = (Speed + AddForce*Time.fixedDeltaTime/RB.mass)/(1+BeakForce*Time.fixedDeltaTime);
RPM = Speed * Radius * 60;

LastSKM = -1;
}
LastPoint = transform.position;
if ( !Sliding){
RB.AddForceAtPosition ( FForce * StaticFriction - Vel * StaticForce, wh.point + transform.up*ForceApPointDistance);
}else{
if ( Vel.magnitude > MaxStaticForce)
Vel = Vel.normalized*MaxStaticForce;
RB.AddForceAtPosition ( FForce * SlidingFriction - Vel * SlidingForce, wh.point + transform.up*ForceApPointDistance);
}
if (WheelMesh)
WheelMesh.RotateAround ( transform.right, RPM * 90 / 60 / Radius * Time.fixedDeltaTime * Mathf.Deg2Rad);

}


З.Ы:
Обновил скрипт, изменил принцип торможения BrakeForce.

Автор - VolkOrievith
Дата добавления - 22 Июн 2016 в 22:14
korveenДата: Сб, 25 Июн 2016, 11:37 | Сообщение # 2
Победитель конкурса GCC
 
Сообщений: 183
Награды: 2
Репутация: 45
Статус: Offline
Посмотрел демку - ездит нормально, но вот на заносах уж по мне слишком сильно перекашивает, даже когда на малой скорости, машино может очень занести. Думаю стоит все же для демки еще чуть-чуть подправить переменные.
Ну а в целом мне понравилось, хорошая альтернатива стандартному


 
СообщениеПосмотрел демку - ездит нормально, но вот на заносах уж по мне слишком сильно перекашивает, даже когда на малой скорости, машино может очень занести. Думаю стоит все же для демки еще чуть-чуть подправить переменные.
Ну а в целом мне понравилось, хорошая альтернатива стандартному

Автор - korveen
Дата добавления - 25 Июн 2016 в 11:37
Форум Игроделов » UNITY3D » ТРАНСПОРТ » Простая замена встроеному Wheel Collider. Колесо скриптом. (Скрипт JS + box collider.)
  • Страница 1 из 1
  • 1
Поиск:
Загрузка...

Game Creating CommUnity © 2009 - 2024