nikolay.sykharev Posted June 7, 2020 Share Posted June 7, 2020 Скрипты приведенные в туторе для версии 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.0f, 6.0f); исправлено player.Position = new vec3(0.0f, -10.0f, 6.0f); Link to comment
fox Posted June 8, 2020 Share Posted June 8, 2020 Здравствуйте, Николай! В версии документации 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
nikolay.sykharev Posted June 9, 2020 Author Share Posted June 9, 2020 On 6/8/2020 at 9:25 AM, fox said: Т.е. итоговый скрипт может быть таким, как описано здесь. Либо можно просто использовать в коде vec3 вместо dvec3 и mat4 вместо dmat4. Благодарю! Еще возник один момент. Скорее всего я еще пока не разобрался до конца со скриптами, но все это я заставил работать только когда унаследовал AppWorldLogic от Component. Автомобиль у меня исправно спавнится, крутит колесами в разные стороны, но вот отчего то проваливается колесами в "землю" на дефолтной сцене. Возможно я тоже в чем то еще не разобрался, однако это странно что автомобиль из тутора на дефолтной сцене, не работает. Может подскажете что может быть не так? Link to comment
fox Posted June 9, 2020 Share Posted June 9, 2020 Здравствуйте, Николай! WheelJoint использует raycasting для определения пересечения с поверхностью, поэтому у "земли" должен быть включен флаг PhysicsIntersection (по умолчанию он выключен). Это можно сделать либо в редакторе на вкладке Parameters после выделения соответствующей ноды, либо при помощи следующего кода (в примере он вроде бы был в 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
nikolay.sykharev Posted June 9, 2020 Author Share Posted June 9, 2020 12 hours ago, fox said: WheelJoint использует raycasting для определения пересечения с поверхностью, поэтому у "земли" должен быть включен флаг PhysicsIntersection (по умолчанию он выключен) Вот я дурилка - точно, и ведь уже тыркал на эту кнопку. Теперь колеса не проваливаются, однако машинка не едет)) Хех. Но с вашим скриптом наконец все заработало как надо, его надо в туториал документации добавить и добавить примечание, что есть серьезные различия в версиях движка и подписках. Еще раз спасибо, будем курить дальше. PS Не надо от версии к версии менять синтаксис скриптов. Будьте человеками! Link to comment
Recommended Posts