Jump to content

Engine crashes with LeaveCallaback in PhysicalTrigger


photo

Recommended Posts

Hi,

we are currently facing an bug which might be linked to this old topic. Setup in the latest engine version (2.16.1): Create two meshes, one with an PhysicalTrigger as child, the other one with an BodyDummy. PhysicalTrigger has two callbacks, one for EnterCallback() and one for LeaveCallback(). When the second mesh with the BodyDummy will be deleted before the LeaveCallback() was triggered, the engine will crash. Doesn't matter, if DeleteLater() or DeleteForce() was called and/or mesh deletion happens in EnterCallback() or during regular update. However, once the LeaveCallback() was triggered, the mesh and BodyDummy can be deleted safely. I used the following code for testing:

Spoiler
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Unigine;

namespace UnigineApp
{
	class AppWorldLogic : WorldLogic
	{
		// World logic, it takes effect only when the world is loaded.
		// These methods are called right after corresponding world script's (UnigineScript) methods.
		private ObjectMeshDynamic mesh1;
		private ObjectMeshDynamic mesh2;
		private PhysicalTrigger trigger;
        private IntPtr collsionEnterTriggerID;
        private IntPtr collsionLeaveTriggerID;

        private float deltaT = 1.0f;
		private bool scaleUp = false;

		float time = 0.0f;
		bool dir = false;
		
		bool shouldDelete=false;
        private int tick = 0;
		public AppWorldLogic()
		{
		}

		public override bool Init()
		{
			// Write here code to be called on world initialization: initialize resources for your world scene during the world start.
			mesh1 = Primitives.CreateSphere(1.0f);
			mesh2 = Primitives.CreateSphere(1.0f);

			trigger = new PhysicalTrigger(Shape.TYPE.SHAPE_SPHERE, vec3.ONE);
			trigger.CollisionMask = 8;
			collsionEnterTriggerID = trigger.AddEnterCallback(OnCollisionEnter);
			collsionLeaveTriggerID = trigger.AddLeaveCallback(OnCollisionLeave);
			mesh1.AddChild(trigger);

			BodyRigid rigid1 = new BodyRigid(mesh1);
			ShapeSphere sphere1 = new ShapeSphere(rigid1, 1.0f);
			sphere1.Mass = 0.0f;
			rigid1.Gravity = false;
			sphere1.CollisionMask = 8;


			BodyDummy rigid2 = new BodyDummy(mesh2);
			rigid2.Gravity = false;
			ShapeSphere sphere2 = new ShapeSphere(rigid2, 1.0f);
			sphere2.Mass = 0.0f;
			sphere2.CollisionMask = 8;

			mesh1.WorldPosition = new vec3(0.0f, -5.0f, 1.0f);
			mesh2.WorldPosition = new vec3(0.0f, 5.0f, 1.0f);


			return true;
		}

		// start of the main loop
		public override bool Update()
		{
            deltaT += Game.IFps;

            mesh1.WorldPosition = new vec3(0.0f, -5.0f * Math.Sin(deltaT), 1.0f);

			if (mesh2 != null)
                mesh2.WorldPosition = new vec3(0.0f, -5.0f * Math.Cos(deltaT), 1.0f);


            // Write here code to be called before updating each render frame: specify all graphics-related functions you want to be called every frame while your application executes.
            if (shouldDelete)
            {
				//Uncomment for "fix"
                //trigger.RemoveLeaveCallback(collsionLeaveTriggerID);
                //trigger.RemoveEnterCallback(collsionEnterTriggerID);

                mesh2.DeleteLater();
				mesh2 = null;

				//"Uncomment for "fix"
				//trigger.UpdateContacts();
                //collsionEnterTriggerID = trigger.AddEnterCallback(OnCollisionEnter);
                //collsionLeaveTriggerID = trigger.AddLeaveCallback(OnCollisionLeave);

                shouldDelete = false;
            }

            return true;
		}

		public override bool PostUpdate()
		{
			// The engine calls this function after updating each render frame: correct behavior after the state of the node has been updated.

			return true;
		}

		public override bool UpdatePhysics()
		{
			// Write here code to be called before updating each physics frame: control physics in your application and put non-rendering calculations.
			// The engine calls UpdatePhysics() with the fixed rate (60 times per second by default) regardless of the FPS value.
			// WARNING: do not create, delete or change transformations of nodes here, because rendering is already in progress.
			trigger.UpdateContacts();
			return true;
		}
		// end of the main loop

		public override bool Shutdown()
		{
			// Write here code to be called on world shutdown: delete resources that were created during world script execution to avoid memory leaks.

			return true;
		}

		public override bool Save(Stream stream)
		{
			// Write here code to be called when the world is saving its state (i.e. state_save is called): save custom user data to a file.

			return true;
		}

		public override bool Restore(Stream stream)
		{
			// Write here code to be called when the world is restoring its state (i.e. state_restore is called): restore custom user data to a file here.

			return true;
		}

        private void OnCollisionEnter(Body body)
        {
			if (tick == 1)
				shouldDelete = true;

			tick++;
		}

        private void OnCollisionLeave(Body body)
        {
            //if (tick == 0)
            //    shouldDelete = true;

            //tick++;
        }
    }
}

 

 

A current workaround (as mentioned in the link post) is to unregister the callbacks, calling DeleteForce() or DeleteLater(), calling UpdateContacts() on the physical trigger and adding the callbacks again.

Best

Christian

 

 

Link to comment
×
×
  • Create New...