Jump to content

[SOLVED] Скрипты из тутора "Creating a Car with Wheel Joints"


photo

Recommended Posts

Скрипты приведенные в туторе для версии 2,10, однако у меня версия SDK 2.11 и синтаксис уже (!!!) отличается. https://developer.unigine.com/en/docs/2.10/code/usage/car_suspension_joints/index

Основные проблемы в неявном преобразовании переменных. 4 ошибки. Насколько правильно я сделал следующее?

ошибка
dmat4 wheel_t = wheel_body.Object.Transform;
исправлено
dmat4 wheel_t = new dmat4(wheel_body.Object.Transform);
 
ошибка
joint.Anchor0 = anchor0;
joint.Anchor1 = anchor1;
исправлено
 joint.Anchor0 = new vec3((float)anchor0.x, (float)anchor0.y, (float)anchor0.z);
joint.Anchor1 = new vec3((float)anchor1.x, (float)anchor1.y, (float)anchor1.z);
 
ошибка
OMD.Transform = transform;
исправлено
OMD.Transform = new mat4(transform);
 
ошибка
 player.Position = new dvec3(0.0f, -10.0f6.0f);
исправлено
 player.Position = new vec3(0.0f, -10.0f6.0f);
Link to comment

Здравствуйте, Николай!

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

#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
	using Vec3 = Unigine.vec3;
	using Vec4 = Unigine.vec4;
	using Mat4 = Unigine.mat4;
#endif

И тогда по аналогии с C++ использовать в коде типы Mat4, Vec3, Vec4, которые будут меняться в зависимости от выбранной точности.

Т.е. итоговый скрипт может быть таким, как описано здесь. Либо можно просто использовать в коде vec3 вместо dvec3 и mat4 вместо dmat4.

В 2.10 этот момент упущен, приносим извинения за неудобства!

Спасибо за сообщение!

Link to comment
On 6/8/2020 at 9:25 AM, fox said:

Т.е. итоговый скрипт может быть таким, как описано здесь. Либо можно просто использовать в коде vec3 вместо dvec3 и mat4 вместо dmat4.

Благодарю!

Еще возник один момент. Скорее всего я еще пока не разобрался до конца со скриптами, но все это я заставил работать только когда унаследовал AppWorldLogic от Component. Автомобиль у меня исправно спавнится, крутит колесами в разные стороны, но вот отчего то проваливается колесами в "землю" на дефолтной сцене. Возможно я тоже в чем то еще не разобрался, однако это странно что автомобиль из тутора на дефолтной сцене, не работает.

Может подскажете что может быть не так?

Link to comment

Здравствуйте, Николай!

WheelJoint использует raycasting для определения пересечения с поверхностью, поэтому у "земли" должен быть включен флаг PhysicsIntersection (по умолчанию он выключен). Это можно сделать либо в редакторе на вкладке Parameters после выделения соответствующей ноды, 

image.png

либо при помощи следующего кода (в примере он вроде бы был в AppWorldLogic.Init() ):

// enabling collision for the ground
Node ground = World.GetNodeByName("ground_plane");
if (ground)
{
	(ground as Unigine.Object).SetCollision(true, 0);
	(ground as Unigine.Object).SetPhysicsIntersection(true, 0);
}

При реализации через компоненты в коде можно обойтись без использования AppWorldLogic.

Можно создать компоненту Car и использовать следующий код (при вставке не забудьте заменить YOUR_GUID в PropertyGuid на то значение, которое было сгенерировано для вашей компоненты):

Spoiler

 


using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;
#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
	using Vec3 = Unigine.vec3;
	using Vec4 = Unigine.vec4;
	using Mat4 = Unigine.mat4;
#endif
[Component(PropertyGuid = "YOUR_GUID")]
public class car : Component
{
	// car parameters
		public float frame_width = 2.0f;
		public float frame_height = 0.5f;
		public float frame_length =4.0f;
		public float wheel_radius = 0.5f;
		public float wheel_width = 0.5f;
		public float mass = 25.0f;
		public Vec3 position = new Vec3(0.0f, 0.0f, 1.0f);
		Mat4 transform;
		
		// movement parameters
		public float angle = 0.0f;
		public float velocity = 0.0f;
		public float torque = 0.0f;

		// car elements
		
		ObjectMeshDynamic car_frame;
		ObjectMeshDynamic[] wheels = new ObjectMeshDynamic[4];
		JointWheel[] wheel_joints = new JointWheel[4];
		Controls controls;

	// function setting up bodies for a wheel joint
		void setBodies(JointWheel joint, BodyRigid car_body, BodyRigid wheel_body)
		{
			joint.Body0 =car_body;
			joint.Body1 =wheel_body;

			Mat4 wheel_t = wheel_body.Object.Transform;

			Vec3 anchor0 = wheel_t.Translate;
			Vec3 anchor1 = Vec3.ZERO;

			vec3 axis00 = vec3.UP;
			vec3 axis10 = vec3.RIGHT;
			vec3 axis11 = (wheel_t.GetRotate() * axis10);

			// setting up joint's anchor and axes
			joint.Anchor0 = anchor0;
			joint.Anchor1 = anchor1;

			joint.Axis00 = axis00;
			joint.Axis10 = axis10;
			joint.Axis11 = axis11;
		}
		/// function, creating a car body having a specified size, color and transformation with a body and a shape
		ObjectMeshDynamic createBody(String name, vec3 size, float mass, vec4 color, Mat4 transform)
		{
			// creating geometry and setting up its parameters (name, material and transformation)
			ObjectMeshDynamic OMD = Primitives.CreateBox(size);
			OMD.WorldTransform = transform;
			OMD.SetMaterial("mesh_base", "*");
			OMD.SetMaterialParameterFloat4("albedo_color", color, 0);
			OMD.Name = name;

			// enabling collision detection for the body
			OMD.SetCollision(true, 0);

			// adding physics, i.e. a rigid body and a box shape with specified mass
			BodyRigid body = new BodyRigid(OMD);

			body.AddShape(new ShapeBox(size), MathLib.Translate(new vec3(0.0f)));
			OMD.Body.GetShape(0).Mass = mass;

			return OMD;
		}

		/// function, creating a wheel having a specified size, color and transformation with a body
		ObjectMeshDynamic createWheel(Node frame, String name, float radius, float height, Mat4 transform)
		{
			// creating geometry and setting up its parameters (name, material and transformation)
			ObjectMeshDynamic OMD = Primitives.CreateCylinder(radius, height, 1, 32);
			frame.AddChild(OMD);
			OMD.Transform = transform;
			OMD.SetMaterial("mesh_base", "*");
			OMD.SetMaterialParameterFloat4("albedo_color", new vec4(0.1f, 0.1f, 0.1f, 1.0f), 0);
			OMD.Name = name;

			// enabling collision detection for the wheel
			OMD.SetCollision(true, 0);

			// adding a rigid body 
			BodyRigid body = new BodyRigid(OMD);

			return OMD;
		}
/// Initializing a car with specified frame and wheel parameters
		public void Init()
		{
			transform = MathLib.Translate(position);
			float delta = 0.2f;

			car_frame = createBody("car_frame", new vec3(frame_width, frame_length, frame_height), 64.0f, new vec4(1.0f, 0.1f, 0.1f, 1.0f), transform);

			// initialization of wheels
			wheels[0] = createWheel(car_frame, "car_wheel_f_l", wheel_radius, wheel_width, new Mat4(MathLib.Translate(-(frame_width + wheel_width) / 2 - delta, frame_length / 2 - wheel_radius, -frame_height / 2) * MathLib.RotateY(90.0f)));
			wheels[1] = createWheel(car_frame, "car_wheel_f_r", wheel_radius, wheel_width, new Mat4(MathLib.Translate((frame_width + wheel_width) / 2 + delta, frame_length / 2 - wheel_radius, -frame_height / 2) * MathLib.RotateY(90.0f)));
			wheels[2] = createWheel(car_frame, "car_wheel_r_l", wheel_radius, wheel_width, new Mat4(MathLib.Translate(-(frame_width + wheel_width) / 2 - delta, -0.25f * frame_length, -frame_height / 2) * MathLib.RotateY(90.0f)));
			wheels[3] = createWheel(car_frame, "car_wheel_r_r", wheel_radius, wheel_width, new Mat4(MathLib.Translate((frame_width + wheel_width) / 2 + delta, -0.25f * frame_length, -frame_height / 2) * MathLib.RotateY(90.0f)));

			// initialization of wheel joints
			for (int i = 0; i < 4; i++)
			{
				wheel_joints[i] = new JointWheel();
				// setting bodies and wheel parameters
				setBodies(wheel_joints[i], car_frame.BodyRigid, wheels[i].BodyRigid);
				wheel_joints[i].WheelRadius = wheel_radius;
				wheel_joints[i].WheelMass = wheel_radius;
				
				// setting restitution parameters
				wheel_joints[i].LinearRestitution = 0.1f;
				wheel_joints[i].AngularRestitution = 0.1f;

				// setting linear damping and spring rigidity
				wheel_joints[i].LinearDamping = 400.0f;
				wheel_joints[i].LinearSpring = 100.0f;

				// setting lower and upper suspension ride limits [-0.15; 0.15]
				wheel_joints[i].LinearLimitFrom = -0.15f;
				wheel_joints[i].LinearLimitTo = 0.15f;
				wheel_joints[i].LinearDistance = 0.0f;

				// setting number of iterations
				wheel_joints[i].NumIterations = 8;
			}

			// setting up player and controls
			PlayerPersecutor player = new PlayerPersecutor();

			player.Fixed = true;
			player.Target = car_frame;
			player.MinDistance = 6.0f;
			player.MaxDistance = 11.0f;
			player.Position = new Vec3(0.0f, -10.0f, 6.0f);
			controls = player.Controls;
			player.Controlled = false;
			player.MainPlayer = true;
			Game.Player = player;
			Game.Enabled = true;

		
		}

		/// method updating current car state with a keyboard control handler
		public void Update()
		{
		
			float ifps = Game.IFps;

			// forward and backward movement by setting joint motor's velocity and torque
			if ((controls.GetState(Controls.STATE_FORWARD) == 1) || (controls.GetState(Controls.STATE_TURN_UP) == 1))
			{
				velocity = MathLib.Max(velocity, 0.0f);
				velocity += ifps * 50.0f;
				torque = 5.0f;
			}//Input.IsKeyDown(Input.KEY.DOWN)
			else if ((controls.GetState(Controls.STATE_BACKWARD) == 1) || (controls.GetState(Controls.STATE_TURN_DOWN) == 1))
			{
				velocity = MathLib.Min(velocity, 0.0f);
				velocity -= ifps * 50.0f;
				torque = 5.0f;
			}
			else
			{
				velocity *= MathLib.Exp(-ifps);
			}
			velocity = MathLib.Clamp(velocity, -90.0f, 90.0f);

			// steering left and right by changing Axis01 for front wheel joints
			if ((controls.GetState(Controls.STATE_MOVE_LEFT) == 1) || (controls.GetState(Controls.STATE_TURN_LEFT) == 1))
				angle += ifps * 100.0f;
			else if ((controls.GetState(Controls.STATE_MOVE_RIGHT) == 1) || (controls.GetState(Controls.STATE_TURN_RIGHT) == 1))
				angle -= ifps * 100.0f;
			else
			{
				if (MathLib.Abs(angle) < 0.25f) angle = 0.0f;
				else angle -= MathLib.Sign(angle) * ifps * 45.0f;
			}
			angle = MathLib.Clamp(angle, -30.0f, 30.0f);

			// calculating steering angles for front joints (angle_0 and angle_1)
			float base_a = 3.3f;
			float width = 3.0f;
			float angle_0 = angle;
			float angle_1 = angle;
			if (MathLib.Abs(angle) > MathLib.EPSILON)
			{
				float radius = base_a / MathLib.Tan(angle * MathLib.DEG2RAD);
				angle_0 = MathLib.Atan(base_a / (radius + width / 2.0f)) * MathLib.RAD2DEG;
				angle_1 = MathLib.Atan(base_a / (radius - width / 2.0f)) * MathLib.RAD2DEG;
			}

			wheel_joints[0].Axis10 = MathLib.RotateZ(angle_0).GetColumn3(0);
			wheel_joints[1].Axis10 = MathLib.RotateZ(angle_1).GetColumn3(0);

			// enabling or disabling a brake
			if (controls.GetState(Controls.STATE_USE) == 1)
			{
				velocity = 0.0f;
				for (int i = 0; i < 4; i++)
					wheel_joints[i].AngularDamping = 20000.0f;
			}
			else
			{
				for (int i = 0; i < 4; i++)
					wheel_joints[i].AngularDamping = 0.0f;
			}

		
		}

		/// method updating car physics
		public void UpdatePhysics()
		{
			// set angular velocity for rear joints
			wheel_joints[2].AngularVelocity = velocity;
			wheel_joints[3].AngularVelocity = velocity;

			// set torque for rear joints
			wheel_joints[2].AngularTorque = torque;
			wheel_joints[3].AngularTorque = torque;

		
		}
}

Затем компоненту можно накинуть на любую ноду в сцене (да хоть на ту же "землю") и после запуска приложения все должно заработать.

Спасибо!

Link to comment
12 hours ago, fox said:

WheelJoint использует raycasting для определения пересечения с поверхностью, поэтому у "земли" должен быть включен флаг PhysicsIntersection (по умолчанию он выключен)

Вот я дурилка - точно, и ведь уже тыркал на эту кнопку. Теперь колеса не проваливаются, однако машинка не едет)) Хех.

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

 

PS

Не надо от версии к версии менять синтаксис скриптов. Будьте человеками!

Link to comment
  • morbid changed the title to [SOLVED] Скрипты из тутора "Creating a Car with Wheel Joints"
×
×
  • Create New...