AddCentralImpulse() Not Working Properly(Unity3d)

Post Reply
EliasNemer
Posts: 15
Joined: Mon Dec 09, 2019 1:10 pm

AddCentralImpulse() Not Working Properly(Unity3d)

Post by EliasNemer »

hello,

i am using BulletUnity Lib,

in my game i am having an issue with my ApplyCentralImpulse function.. at the start of the game 2 cue balls are instantiated and the Lag Shot(part of a billiard game which dictates who breaks) is set to proceed..

now if i pull on my slider directly after i start the game in the editor and let go, the correct outcome happens which is that both balls are projected forward..

the ApplyCentralImpulse worked for both GO's

now if i start the game and wait 1 second, then click on the slider to take the shot, the code still registers the cuestick pull back, and also with my print function executed the line before the ApplyCentralImpulse function for both balls..

But the ApplyImpulse does not work..

through testing i found that this is somehow connected to the fixed update of the BPhysicsWorld. by which i mean if i decrease the fixed update from 0.01 to 0.001, i could wait 10 seconds and the correct outcome will happen, but ofcoarse i dont want to wait 10 seconds i just want it to work..

here is some of the code

Code: Select all

void Update()
    {
        if(gameManager.getLagShotPrepared() && !lagShotDetailsPrepared)
        {
            PrepareLagShotDetails();
            return;
        }
        if (lagShotDetailsPrepared && gameManager.getLagShotInPlay())
        {
            if (cueInstantiator.getCuePlayerTwoAvailable() && cueInstantiator.getCuePlayerOneAvailable())
            {
                PlaceCueStick();
                mouseCheck();
                PORSetter();
                CueStriker();
            }
            else if (!cueInstantiator.getCuePlayerTwoAvailable() && cueBallPlayerTwo.angularVelocity.magnitude < 0.005f && !gotFinalPosition)
            {
                PORSetter();
                FinalPosition();
            }
            return;
        }
}
 
void mouseCheck()
    {
        if (!touchInput)
        {
            if (Input.GetMouseButtonDown(0))
            {
                mouseButtonDown = true;
                mouseButtonUp = false;
                slider.onValueChanged.AddListener(CueSliderManager);
                print("CueManager: MouseButton is Down");
            }
            else if (Input.GetMouseButtonUp(0))
            {  
                mouseButtonDown = false;
                mouseButtonUp = true;
                print("CueManager: MouseButton is UP");
            }
        }
        if (touchInput)
        {
            if (Input.touchCount > 0)
            {
                mouseButtonDown = true;
                mouseButtonUp = false;
                slider.onValueChanged.AddListener(CueSliderManager);
            }
            else if (Input.touchCount == 0)
            {
                mouseButtonDown = false;
                mouseButtonUp = true;
            }
        }
    }
    
    private void FixedUpdate()
    {
        if (hitBall)
        {
         //this is not working at every attemp, only if i start and quickly shoot
            cueBallPlayerOne.RigidBody.ApplyCentralImpulse(new Vector3(force.x + randomForceSave, force.y, force.z).ToBullet());
            cueBallPlayerTwo.RigidBody.ApplyCentralImpulse(new Vector3(force.x, force.y, force.z).ToBullet());
            hitBall = false;
        }
    }
    
//it is in this function that the issue occurs
void CueStriker()
    {
        if (!mouseButtonUp || !cueManagerActive || !strike)
        {
            return;
        }
 
        slider.value = 0;
        strike = false;
 
        if(gameManager.getLagShotInPlay())
        {
            float randomAddForce = Random.Range (0.1f, 0.3f); //just for demo
            int negativeOrPositive = Random.Range (0, 2);
            if (negativeOrPositive == 1)
            randomAddForce = -randomAddForce;
       		randomForceSave = randomAddForce;
           	print("Doing This"); // this is woking at every attemp 
            	hitBall = true;

        }else
        {
            cueBall.RigidBody.ApplyImpulse(force.ToBullet(), positionToHit.ToBullet());
        }
 
        cuePositionDraw = Vector3.zero;
        slider.value = 0;
        cueManagerActive = false;
        shotTaken = true;
    }
 
public void CueSliderManager(float drawBack)
    {
        if(gameManager.getLagShotInPlay())
        {
            if (!mouseButtonUp)
            {
                cuePositionDraw = unitVector*MAX_DRAWBACK * Mathf.Pow(drawBack, 2f);
                cueStrength = (MAX_CUE_FORCE * Mathf.Pow(drawBack, 2f));
                force = new Vector3(cueStrength,0,0);
 
                cueManagerActive = true;
                strike = true;
 
                if (drawBack == 0)
                    strike = false;    
            }
        }
        if (!gameManager.getLagShotInPlay())
        {
            if (!mouseButtonUp)
            {
                cuePositionDraw = unitVector * MAX_DRAWBACK * Mathf.Pow(drawBack, 2f);
                cueStrength = (MAX_CUE_FORCE * Mathf.Pow(drawBack, 2f));
                force = (-1) * unitVector * cueStrength;
 
                positionToHit = new Vector3((cueBallGUI.getCueHitPositionRatio().x * CUEBALL_RADIUS * (-1) * unitVector.z), (cueBallGUI.getCueHitPositionRatio().y * CUEBALL_RADIUS), (cueBallGUI.getCueHitPositionRatio().x * CUEBALL_RADIUS * unitVector.x));
 
                cueManagerActive = true;
                strike = true;
 
                if (drawBack == 0)
                    strike = false;
               
            }
        }
    }
here is a link to a video showing the difference between fixed updates and their effect.. Any information about the why this is happening or the relevance to why fixed update matters.. i dont want it to matter.. as in i dont want it to be related at least in its performance aspect.

https://youtu.be/Xsfl2jA6AtI
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: AddCentralImpulse() Not Working Properly(Unity3d)

Post by drleviathan »

My guess is the RigidBody is going inactive after the default 2 seconds. If you first activate (probably cueBall.RigidBody.Activate() or something like that) before applying the impulse it might work.

Bullet will deactivate dynamic RigidBodies whose velocities are below some thresholds for longer than 2 seconds. When a dynamic object bumps into others they will automatically be activated, but btRigidBody::applyImpulse() does not do it.

Edit: changed wording to be more correct: "who are not moving" --> "whose velocities are below some thresholds"

Also I should mention for future readers: if you do call applyImpulse() on deactivated bodies and then later the bodies are activated by some other means then the accumulated impulses will apply at that moment and the object will go flying or spinning away.
EliasNemer
Posts: 15
Joined: Mon Dec 09, 2019 1:10 pm

Re: AddCentralImpulse() Not Working Properly(Unity3d)

Post by EliasNemer »

THAAAANK YOUU!! 100%
Post Reply