Unity3D forcing object to a given orientation with minimum artificial effect - unity3d

In my board game, the points are given by throwing 7 sea-shells cowry shell. These shells are dropped onto a sphere in Unity so they get rolled over randomly to different places. Once the rigidbody.isSleeping() returns true, I do a Raycast(from the belly side downwards) to figure out the orientation of the shell. If it is NOT a hit we know the shells belly is turned upside which means a point.
All is good and very realistic when in single player mode. Reason is I just activate the gravity of the shells and they dropped on to sphere, gets rolled randomly and when stopped i get the marks as stated above.
Now the problem is I am making the game multiplayer. In this case, I sent the randomly generated marks from the server and client will have to animate the shells to represent the marks. For example, if server send 3, out of 7 shells, 3 should have it's belly turned upside.
Trying to do this has been a major problem for me. I tried to transform.Rotate() when the velocity is reduced but it was not very reliable and sometimes acts crazy. Rotating afterrigidbody.isSleeping() works but very unrealistic.
I know I am trying to defy physics here, but there may be some ways to achieve what I want with minimum artificial effect.
I actually need some ideas.
Update - 1
After infor I receive below, I did found some information here, some advanced stuff here. Since the latter link had some advanced stuff, I wanted to start small. So I followed the first link and did below test.
I recorded the position, rotation & velocity of the sea shell with autosimulation enabled and logged them to a file. Then i used the Physics.Simulate() for the same scenario and logged the same.
Comparing the two tells me that data in both cases are kind of similar. So seems like for my requirements I need to simulate the sea-shell drop and then apply that sequence to the actual object.
Now my problem is how can I apply the results of physics.simulate() results (position, rotation, velocity etc..) to the actual sea-shell so the animation can be seen. If I set the positions to my gameobject within the simulation loop nothing happens.
public void Simulate()
{
rbdy = GetComponent<Rigidbody>();
rbdy.AddForce(new Vector3(0f, 0f, 10f));
rbdy.useGravity = true;
rbdy.mass = 1f;
//Simulate where it will be in 5 seconds
int i = 0;
while (simulateTime >= Time.fixedDeltaTime)
{
simulateTime -= Time.fixedDeltaTime;
Debug.Log($"position: {rbdy.position.ToString()} rotation: {rbdy.rotation.ToString()} Velocity {rbdy.velocity.magnitude}");
gameObject.transform.position = rbdy.position;
Physics.Simulate(Time.fixedDeltaTime);
}
}
So, how can I get this simulated data applied to actual gameobject in the scene?

Assume Physics are deterministic, just set the velocity and position and let it simulate on each client. Output should be the same. If the output differs slighly, you could adjust it and it may be only barely noticable.
Physics.simulate may be interesting to read, even if it's kind of the opposite of what you want.
You can throw in the client, record the steps in realtime or using physics.simulate (see point 2) and transmit the animation data as binary - then use it in the other clients to play the animation.

Related

Stuck Implementing A Way To Rotate A Rigidbody Towards A Point With Rigidbody.AddTorque

So I am kinda stuck on what to do now because as I said I am trying to use Rigidbody.AddTorque to rotate a rigid body towards a certain point, which I was going to use to align a player with a gravitational pull so they can be upright. I have got the input part of the code, I just don't have a way to rotate the player to align with it, without violating the laws of physics with Quaternion.FromToRotation and messing with my character controller too, which I am trying to make entirely physics based rotation wise too to avoid any other problems.
I have experimented with a couple of methods, first I tried adapting my character controller code which used Rigidbody.AddForce to move the player and also dampening unwanted movements, as Rigidbody.AddTorque is basically Rigidbody.AddForce but for rotations, however, it was too weak and just flopping around when I tried it, here's the code for the character controller for calculating the force needed for one axes:
if(projected_speed.x*speed == relative_v.x)
{
applied_speed.x = 0f;
}
else if(Mathf.Sign(projected_speed.x)== -1)
{
applied_speed.x = relative_v.x - Mathf.Abs(projected_speed.x*speed);
}
else if (Mathf.Sign(projected_speed.x) == 1)
{
applied_speed.x = projected_speed.x*speed - relative_v.x;
}
Where projected_speed is the speed the controller wants to be at,relative_v is the relative velocity, and applied_speed is the speed that will be actually applied in Rigidbody.AddForce.
Anyways so maybe I didn't use enough force, as the player is under a gravitational pull, but that would have probably made it flip out or something, anyways so the second thing I tried was a PID controller, and I managed to find a page which explains it pretty well, sadly don't have the link anymore, but when I tried this because you have to tune it, I was stuck doing it, and it just wasn't able to do anything and was just rolling around the floor and sometimes spinning, probably as it couldn't cope with gravity, so that didn't work, so does anyone know how I could finally do this and make my character able to right themselves according to gravity?
Sorry for not indicating that my issue is solved, click here for the answer, credit to Ruzihm.

Best way to prevent physics calculations in Unity from eating too much FPS?

I'm a senior software engineer, but completely new to Unity programming. I've been teaching myself Unity for a few weeks by writing some SteamVR toys for myself. I wanted to ask about Unity's standard built-in ways to improve frame rate for a program with a lot of intensive physics calculation.
In my current VR scene, I have a ball with a Rigidbody on it. When I pick it up and throw it, I let it move naturally, but I apply small forces on every Update() call to adjust the landing position and always hit a target.
I saw my framerate take a big dive, so I wrote my own function to throttle the updates, limiting them to 5 per second. The question is, is there some standard Unity behavior that I should be using instead of rolling this code myself?
In my throwing script, I maintain a bunch of top level variables and update them first to decide whether I should do calculations on the current frame.
private void updateCalculationFrame() {
isCalculationFrame = Time.time > nextCalculationTime;
while (nextCalculationTime < Time.time) {
nextCalculationTime += (1 / calculationsPerSecond);
}
}
On each frame, I run this function, then if isCalculationFrame is true, I proceed to calculate and add force vectors. I just wonder if I am overlooking some more standard way to do this with less code? I feel like this must be a very common thing to try to do.
The code you have there will freeze the Unity until the loop is finished. You shouldn't do this at all.
You could simply set a new Time.fixedDeltaTime. By default it is usually about 0.02 but you can set it to anything you want.
The interval in seconds at which physics and other fixed frame rate updates (like MonoBehaviour's FixedUpdate) are performed.
...
Note that the fixedDeltaTime interval is with respect to the in-game time affected by timeScale.

Unity returning incorrect transform.rotation

In the endless running game I am creating, there is a mechanic called the jump pad. It basically takes in the change in the player's position since the last frame and converts that to an angle. Then it uses that along with the transform.rotation of the jump pad to figure out which direction to move the player in, as if it was actually bouncing off of it.
This algorithm would've been working perfectly except for one problem: Unity was reading an incorrect transform.rotation. When the jump pad was rotated 45 degrees, it read 21.92615 (after being multiplied with Mathf.Rad2Deg.) When the jump pad was rotated 20 degrees, it read 9.949307.
At first I thought it was being multiplied by an unknown constant for some reason, but after checking it through the Calculator app I found this to be not exactly the case. After a bit more experimenting I found that the possible "unknown constants", while close enough together, did seem to have a range from around 2 to around 2.1. And while I don't have the faintest clue how this is happening, it does seem to be remarkably consistent.
So my question is: what is this problem I am facing and is there any way I can fix it? Brief side note: I know this is not some other problem with the code because I stripped it down to the bare minimum:
public void OnTriggerEnter2D(Collider2D collision){
Debug.Log(collision.gameObject.transform.rotation.z * Mathf.Rad2Deg);
}
OK. After looking up the scripting API for transform.rotation and messing around a bit, I discovered that it was returning the z value of a quaternion and fixed it using the .ToEulerAngles() call.

Best way to move a game object in Unity 3D

I'm going through a few different Unity tutorials and the way a game object is moved around in each is a little different.
What are the pros/cons to each of these methods and which is preferred for a first person RPG?
// Here I use MovePosition function on the rigid body of this component
Rigidbody.MovePosition(m_Rigidbody.position + movement);
//Here I apply force to the rigid body and am able to choose force mode
Rigidbody.AddForce(15 * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
// Here I directly change a transforms position value, in this case the cam
Transform.transform.position = playerTransform.position + cameraOffset;
Thanks!!
EDIT;
Something I have noticed is that the applied force seems to memic wheeled vehicles while the position changes memic walking/running.
RigidBodies and Velocities/Physics
The only time, I personally have used the rigidbodys system was when implementing my own boids (flocking behaviour) as you need to calculate a few separate vectors and apply them all to the unit.
Rigidbody.MovePosition(m_Rigidbody.position + movement);
This calculates a movement vector towards a target for you using the physics system, so the object's velocity and movement can still be affected by drag, angular drag and so on.
This particular function is a wrapper around Rigidbody.AddForce I believe.
Pros :
Good if realistic physical reactions is something you are going for
Cons:
A bit unwieldy to use if all you are trying to achieve is moving a object from point A to point B.
Sometimes an errant setting set too high somewhere (for example: Mass > 10000000) can cause really screwy bugs in behaviour that can be quite a pain to pin down and mitigate.
Notes: Rigidbodies when colliding with another Rigidbody would bounce from each other depending on physics settings.
They are also affected by gravity. Basically they try to mimic real life objects but it can be sometimes difficult to tame the objects and make them do exactly what you want.
And Rigidbody.AddForce is basically the same as above except you calculate the vector yourself.
So for example to get a vector towards a target you would do
Vector3 target = target.position - myPosition;
Rigidbody.AddForce(target * 15 * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
If you don't plan on having any major physics mechanics in your game, I would suggest moving by interpolating the objects position.
As it is far easier to get things to behave how you want, unless of course you are going for physical realism!
Interpolating the units position
Pros :
Perhaps a little strange to understand at first but far simpler to make objects move how you want
Cons:
If you wanted realistic reactions to objects impacting you'd have to do a lot of the work yourself. But sometimes this is preferable to using a physics system then trying, as I've said earlier to tame it.
You would use the technique in say a Pokemon game, you don't stop in Pokemon and wait for ash to stop skidding or hit a wall and bounce uncontrollably backwards.
This particular function is setting the objects position like teleporting but you can also use this to move the character smoothly to a position. I suggest looking up 'tweens' for smoothly interpolating between variables.
//change the characters x by + 1 every tick,
Transform.transform.position.x += 1f;
Rigidbody.MovePosition(m_Rigidbody.position + movement);
From the docs:
If Rigidbody interpolation is enabled on the Rigidbody, calling Rigidbody.MovePosition results in a smooth transition between the two positions in any intermediate frames rendered. This should be used if you want to continuously move a rigidbody in each FixedUpdate.
https://docs.unity3d.com/ScriptReference/Rigidbody.MovePosition.html
Rigidbody.AddForce(15 * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
This will make the object accelerate, so it won't travel at a constant velocity (this is because of Newton's second law, Force=mass*acceleration). Also if you have another force going in the opposite direction this force could get cancelled out and the object won't move at all.
Transform.transform.position = playerTransform.position + cameraOffset;
This will teleport the object. No smooth transition, no interaction with any forces already in the game, just an instant change in position.

How to prevent characters to overlap

I'm really struggling at something that I had imagined to be pretty simple: I have two meshes (fighters) instantiated from the same prefab and I want them to not overlap. The prefab is set to have a box collider. Ideally, I let the animator handles the position. I've tried several approaches:
Configure the animators to "Animate Physics". No collision is detected
Uncheck root motion and move characters using game object's transform's position. No collision is detected
Uncheck root motion, add a rigid body to each character and move character using game object's position. Collision is detected, but the reaction is governed by physics which makes it look unnatural since all I want is to just avoid the characters to pass through each other i.e. just want characters to be pushed back until they don't collide anymore
I really would like to avoid going with a manual approach to this. How would I prevent this overlapping?
Edit: isTrigger is unset on box colliders
A rigidbody is highly configurable and you want a limited set of the physics functionality it can offer. Go with the third solution you enumerated and freeze the rotation in the rigidbody. See the rigidbody page for more details.
As a side note, you might consider using a capsule collider, so that characters "slide" around each other more easily.
Although it's not necessarily preventing overlap, you could create a perimeter for characters. It would be rather simple depending on what you're doing.
If you want to set up a distance perimeter to prevent characters from getting too close to one another you could use the following equation
Vector3 focalPOne = focalPointOfCharacterOne();
Vector3 focalPTwo = focalPointOfCharacterTwo();
float dx = focalPOne.x - focalPTwo.x;
float dy = focalPOne.y - focalPTwo.y;
float dz = focalPOne.z - focalPTwo.z;
// calc distance along z plane
if (Math.Sqrt((dx * dx) + (dy * dy)) < minDistance)
{
// person is too close to the others head.
if (Math.abs(dz) < minHeightAbove)
{
// go to previous position.
}
// if there is no vertical elivation, you can go
// straight to moving them back to previous position
}
enter code here
If this wasn't what you're looking for, please let me know so I can edit or remove it.
The perimeter created would look something like this.
In order to have your characters with their respective box colliders register a collision, both need to have a RigidBody component. That's the only way to make sure the characters do not go through each other considering they share a prefab.
You don't have to handle the separation/rejection of the characters via the physics engine though. Simply make the box collider trigger, and then handle the separation via code in a C# script using onTiggerEnter.
There's a collision detection matrix that could help you, found here: https://docs.unity3d.com/Manual/CollidersOverview.html. Also this image summarizes it beautifully (in the documentation it's in two separate tables for some reason):