sevas55 Posted November 5, 2024 Posted November 5, 2024 (edited) По примеру отсюда создаю в коде несколько сфер, которые по физике притягиваются в некоторую точку (демо работы трубки осциллографа) При создании сферы функция OMD.SetCollision(false, 0) почему-то не отключает коллизию и сферы сталкиваются между собой, а мне столкновения не нужны. https://youtu.be/uwDZNJbXqHc Подскажите где я ошибся? Вот мой код, в сцену надо добавить Dummy с именем CathodeDummy и в настройках мира нужно обнулить гравитацию Spoiler using System.Collections; using System.Collections.Generic; using Unigine; [Component(PropertyGuid = "cf1779da44f5db9b596a72d5b9691824fb28b657")] public class Oscilloscope : Component { List<BodyRigid> ElectronList = new List<BodyRigid>(); int ElectronCount = 10; Node NodeCathodeDummy = World.GetNodeByName("CathodeDummy"); BodyRigid CreateElectron() { ObjectMeshDynamic OMD = Primitives.CreateSphere(0.05f, 12, 12); // OMD.Transform = MathLib.Translate(0.0f, 0.0f, 1.0f); OMD.SetCollision(false, 0); OMD.SetMaterialParameterFloat4("albedo_color", new vec4(255, 255, 0, 1.0f), 0); BodyRigid br = new BodyRigid(OMD); br.AddShape(new ShapeSphere(0.1f)); OMD.Body.GetShape(0).Mass = 1f; return br; } void Init() { for (int i = 0; i < ElectronCount; i++) { BodyRigid el = CreateElectron(); ElectronList.Add(el); } for (int i = 0; i < ElectronCount; i++) { float x,y,z; float forceMax = 2f; x = MathLib.RandFloat(-forceMax,forceMax); y = MathLib.RandFloat(-forceMax,forceMax); z = MathLib.RandFloat(-forceMax,forceMax); // vec3 x = MathLib.RandVec3((-1)*vec3.ONE, 1*vec3.ONE); ElectronList[i].AddWorldForce(vec3.ZERO, new vec3(x,y,z)); } Visualizer.Enabled = true; } void Update() { float Attr1X=0.5f, Attr1Y=1, Attr1Z=1; vec3 Attr1Pos = new vec3(Attr1X, Attr1Y, Attr1Z);//координаты 1го ускорителя Visualizer.RenderVector(vec3.ZERO,Attr1Pos,vec4.RED); for (int i = 0; i < ElectronList.Count; i++) { //притяжение к ускорителю 1 vec3 VecDist2Attract1 = (vec3)(Attr1Pos - ElectronList[i].Position);//векторное расстояние float Dist2Attract1 = VecDist2Attract1.Length2;//линейное расстояние float ForceAttr1 = 1/(Dist2Attract1+0.1f);//закон тяготения ElectronList[i].AddWorldForce(ElectronList[i].Position, ForceAttr1*VecDist2Attract1.Normalized); // Visualizer.RenderVector(ElectronList[i].Position,0.1*VecDist2Attract1,vec4.GREEN,0.1f); double d = MathLib.Distance2 (ElectronList[i].Position, vec3.ZERO); if (d > 20 ) { float x=0,y=0,z=0; //возврат электрона в нить накала z = MathLib.RandFloat(0, 0.5f); ElectronList[i].Position = new vec3(0,0,z); //после возврата снова добавляем толчок электрону чтобы он улетел float forceMax = 0.5f; x = MathLib.RandFloat(-forceMax,forceMax); y = MathLib.RandFloat(-forceMax,forceMax); z = MathLib.RandFloat(-forceMax,forceMax); vec3 forceEmission = new vec3(x,y,z); // ElectronList[i].AddWorldForce(vec3.ZERO, forceEmission); // Log.Message("{0}"+'\n', VecDist2Attract1); } } } } Заранее спасибо Edited November 5, 2024 by sevas55
sevas55 Posted November 6, 2024 Author Posted November 6, 2024 (edited) Прикрепляю готовый проект (605 МБ) Edited November 6, 2024 by sevas55
mifril Posted November 6, 2024 Posted November 6, 2024 Здравствуйте! Пока сразу на что обратил внимание. Вы создаете для объектов физическое тело(BodyRigid), а метод SetCollision вызываете у самого объекта, этот метод нужен когда у объекта нет физического тела оно статично находится в сцене но мы хотим, чтобы физичные объекты получали информацию о коллизиях с ними. Но когда у объекта есть физическое тело настройки коллизий у поверхностей не учитываются. Попробуйте выставлять в параметры шейпа который добавляете в тело маску Exclusion. Например setExclusionMask(1). https://developer.unigine.com/en/docs/future/principles/physics/collision/ - задесь можно прочитать о том что я хотел объяснить, если Вы не доконца поняли о чем я говорю. 1
sevas55 Posted November 6, 2024 Author Posted November 6, 2024 Добавил OMD.Body.GetShape(0).ExclusionMask = 1; Теперь объекты не сталкиваются между собой. Подскажите, как решить задачу правильно, я сделал как смог, но не уверен, что оптимально с точки зрения эффективности кода. Мне принципиально иметь возможность применять к объекту силу функцией AddWorldForce, чтобы движок сам просчитывал их движение, учитывая массу и было похоже на симуляцию движения в гравитационном поле. Но также важно чтобы объекты не сталкивались между собой. Код не прошу, хотя бы тезисно: создаем RigidBody=> и так далее. Благодарю за помощь.
mifril Posted November 7, 2024 Posted November 7, 2024 Здравствуйте! Я так понимаю, что задача решена и Вы просто хотите убедиться в эффективности решения? В общем пайплайн правильный создаете объект, добавляете к нему RigidBody, к RigidBody добавляете шейпы, если важно можете настроить их как нужно и придавать силу в нужной точке, а не в центре объекта, это позволит достичь более точной симуляции. Если же вы рассматриваете объекты как материальные точки то шейпа сферы будет достаточно и придавать силу в центре шейпа. Так же в настройках щейпа можно выставить маски колизий, по ним будут определяться объекты с которыми шейп может коллизится, можете выставить какую-то опредленную маску этим объектам и объектам с которыми ваши созданные объекты должны колизится. Маска Exclusion нужна чтобы объекты с одинаковими такими масками не колизились, то есть для своих объектов надо выставлять такие маски. Если все объекты у Вас одинаковые, то можете подготовить такой объект в редакторе и сохранить его как NodeReference, а потом в коде уже просто их создавать из NodeReference без дополнительных настроек. 1
sevas55 Posted November 7, 2024 Author Posted November 7, 2024 Да, задача решена. SOLVED Cпасибо за пояснения и помощь!
mifril Posted November 7, 2024 Posted November 7, 2024 Единственное что забыл уточнить, что работать с физикой нужно в методе UpdatePhysics, а не в обычном Update. Так как в UpdatePhysics стабильный фреймрейт и и физичный движок вызывает эту функцию перед каждым своим обновлением.
Recommended Posts