Unity .GetParticles() high CPU spike - unity3d

Im using .GetParticles() on a particlesystem to then destroy the particles when they are outisde of a certain range. My script is below and the particle system variable is cached. I attached the deep profile picture of what is taking the CPU and it points to GetParticles(). I can't find any documentation to why this would be a bad approach, as the script is only attached to one single game object.
Any insight appreciated, thanks!
private void Update()
{if (Time.time > (delayTimer + 0.02f))
{
delayTimer = Time.time;
transform.position = new Vector3(transform.position.x, Water.transform.position.y - 2f, transform.position.z);
//Gets the change in the waters height and resets it
var waterHeightChange = Mathf.Abs(Water.transform.position.y - waterHeight);
waterHeight = Water.transform.position.y;
//Gets the distance to the top of the water to pop the bubble if surpassed
var DistanceToDestroy = Mathf.Abs((Water.transform.position.y + (Water.transform.localScale.y / 2f) - .15f) - transform.position.y);
//Creates a particle array sized a the emitters maximum particles
//Gets the particles from the emitter system and transfers into array of particles, returns total number of particles
//Only called on occasion (once at start really) to make allocation as minimal as possible
if (pSystemParticles == null || pSystemParticles.Length < pSystem.main.maxParticles)
{
pSystemParticles = new ParticleSystem.Particle[pSystem.main.maxParticles];
}
int numParticlesAlive = pSystem.GetParticles(pSystemParticles);
for (int i = 0; i < numParticlesAlive; i++)
{
//Changes the height accordingly for each particle
newPos.Set(pSystemParticles[i].position.x, pSystemParticles[i].position.y, pSystemParticles[i].position.z + waterHeightChange);
//Grab the 'y' positional height relative to the emitter
var particleHeight = newPos.z;
if (particleHeight >= DistanceToDestroy)
{
//Deletes particle if needed
pSystemParticles[i].remainingLifetime = 0;
}
}
//Sets the particle system from the modified array
pSystem.SetParticles(pSystemParticles, numParticlesAlive);
}
}

I'm not sure why you get this spike but this seems to be outside of your control. Maybe you could use the Collision Module, put an invisible plane above your waterline where the particles should stop and then set up the collision module such that the particles lose their whole lifetime when they collide (Lifetime Loss = 1). That way they should disappear when colliding with the plane. Could be faster because particles would never have to enter the C# world plus it's a lot less code to write.

Related

Translated grapple physics from Processing to Unity to get different results

tl;dr Moving my game from Processing to Unity. Code responsible for grappling by manually changing the player's velocity doesn't work even though it's basically copy/pasted.
Hi, I've been working on a project of mine over the summer on Processing, and last week I decided to translate it over to Unity.
What I'm having a problem with is the grapple/rope physics. It's supposed to essentially keep the player inside a circle (made by the endpoint of the rope and the length of the rope). When the player falls outside of this circle, the player's position is moved back to the edge of the circle and the player's velocity is set to tangent of the circle.
Decreasing the length of the rope while swinging is supposed to speed you up. (See Floating Point)
On Processing, it works perfectly just as described above, but when I basically copy/pasted the code into unity it loses momentum too quickly (always ends up stopping at the same angle on the other side the player started on). Here is the code for both (run on each physics frame):
(I've also made some images to describe the motion that both versions produce)
Processing
Code
(warning: bad and redundant)
physics update:
exists = (endPoint != null);
if(lgth<=0) lgth = 1;
if(exists) {
currentLength = phs.position.dist(endPoint);
if(currentLength > lgth) {
float angle = getAngle(endPoint, phs.position);
phs.addPosition(abs(currentLength - lgth), angle);
float angleBetween = getAngle(phs.position, endPoint);
PVector relativeVelocity = new PVector(phs.velocity.x + phs.position.x, phs.velocity.y + phs.position.y);
float displacement = angleBetween - 90;
Line l1 = lineFromTwoPoints(relativeVelocity, endPoint);
Line l2 = lineFromAngle(phs.position, displacement);
PVector pointToLerpTo = intersection(l1, l2);
if(pointToLerpTo!=null) {
phs.velocity.x = pointToLerpTo.x-phs.position.x;
phs.velocity.y = pointToLerpTo.y-phs.position.y;
}
else phs.velocity.mult(0);
}
}
when the player shortens the rope, speed increases:
if(exists) {
float newLgth = lgth-d;
float distance = getDistance(phs.position, endPoint);
if(distance > newLgth) {
float ratio = (distance-newLgth)/lgth;
phs.velocity.setMag(phs.velocity.mag()*(1+ratio));
}
lgth = newLgth;
}
Motion from Processing (good)
Player starts by moving downwards at left edge of rope circle. Doesn't lose speed and continues going around multiple times until gravity slows it down.
Unity
Code
both code blocks from above are handled in the same place here, under FixedUpdate() (problematic part seems to be the velocity section)
distance = Vector2.Distance(transform.position, endpoint);
if(connected && distance > length) {
//lerp position -> endpoint// keep gameObject within length of the rope
float posLerpAmount = (distance - length) / distance;
transform.position = Vector2.Lerp(transform.position, endpoint, posLerpAmount);
//'lerp' velocity -> endpoint// keep the velocity locked to the tangent of the circle around the endpoint
Vector2 relativeVelocity = GetComponent<Rigidbody2D>().velocity + (Vector2)transform.position;
Line l1 = Geometry.LineFromTwoPoints(relativeVelocity, endpoint);
Line l2 = Geometry.LineFromAngle(transform.position, Geometry.GetAngle(endpoint, transform.position) - 90);
if(!Geometry.AreParallel(l1, l2)) {
Vector2 pointToLerpTo = Geometry.Intersection(l1, l2) - (Vector2)transform.position;
GetComponent<Rigidbody2D>().velocity = pointToLerpTo;
}
else GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0);
//increases the magnitude of the velocity based on how far the rope moved the object's position
float ratio = (distance - length) / length;
GetComponent<Rigidbody2D>().velocity *= 1 + ratio;
distance = length;
}
Motion from Unity (bad)
Player starts by moving downward at left edge of rope circle. Gains a little bit of speed from gravity, then will always stop 45 degrees on the other side where it started (regardless of starting speed), then slowly fall back down to the bottom of the circle.
If anyone needs me to explain the Geometry class (lines, intersections) then I can, but I think it's mostly self-explanatory. Otherwise, I think I explained this the best I could. Thanks in advance for any help.
(also, StackOverflow isn't letting me add the Unity2d tag so I guess I gotta settle for Unity3d)
I found out that Rigidbody2D.velocity.magnitude is not how far the object moves every physics update. This is what was causing the issue, because the Processing code was based off the velocity being added directly to the position every update.
To fix this, what I did was do the same geometry, but scale the velocity to the % of how much of the velocity was actually 'used' (it usually travels 2% of the actual velocity vector).
Here is the final code in Unity: (this time I'm showing the fill FixedUpdate(), with the irrelevant parts removed)
float lastMagnitude;
Vector2 lastPosition;
void FixedUpdate() {
float velocityMoved = Vector2.Distance(lastPosition, transform.position) / lastMagnitude;
Debug.Log(velocityMoved * 100 + "%"); //this is usually 2%
bool shortenedRope = false;
if(Input.GetButton("Shorten Rope")) {
shortenedRope = true;
length -= ropeShortenLength;
}
distance = Vector2.Distance(transform.position, endpoint);
if(connected && distance > length) {
//lerp position -> endpoint// keep gameObject within length of the rope
float posLerpAmount = (distance - length) / distance;
transform.position = Vector2.Lerp(transform.position, endpoint, posLerpAmount);
//'lerp' velocity -> endpoint// keep the velocity locked to the tangent of the circle around the endpoint
Vector2 adjustedVelocity = rigidbody.velocity * velocityMoved;
Vector2 relativeVelocity = adjustedVelocity + (Vector2)transform.position;
Line l1 = Geometry.LineFromTwoPoints(relativeVelocity, endpoint);
Line l2 = Geometry.LineFromAngle(transform.position, Geometry.GetAngle(endpoint, transform.position) - 90);
if(!Geometry.AreParallel(l1, l2)) {
Vector2 pointToLerpTo = Geometry.Intersection(l1, l2) - (Vector2)transform.position;
rigidbody.velocity = pointToLerpTo;
rigidbody.velocity /= velocityMoved;
}
else rigidbody.velocity = new Vector2(0, 0);
//'give back' the energy it lost from moving it's position
if(shortenedRope) {
float ratio = (distance - length) / length;
rigidbody.velocity *= 1 + ratio;
}
distance = length;
}
lastPosition = transform.position;
lastMagnitude = rigidbody.velocity.magnitude;
}
EDIT: Recently learned that it is better to use Time.deltaFixedTime instead of the variable I made velocityMoved, since Time.deltaFixedTime is already calculated.

How to filter point clouds by creating a retangle with touches on a Tango phone

I am scanning 3D objects using tango. Now I touches 4 points on the screen to make a rectangle and then remove all point clouds outside this rectangle.
But I have checked the "Point To Point" example provided in the Tango SDK but I do not understand the relationship between point clouds and touch position on the screen. In the "TangoPointCloud.cs" file, point clouds are transformed to the world space as follows:
public void OnTangoPointCloudAvailable(TangoPointCloudData pointCloud)
{
m_mostRecentPointCloud = pointCloud;
// Calculate the time since the last successful depth data
// collection.
if (m_depthTimestamp != 0.0)
{
m_depthDeltaTime = (float)((pointCloud.m_timestamp - m_depthTimestamp) * 1000.0);
}
// Fill in the data to draw the point cloud.
m_pointsCount = pointCloud.m_numPoints;
if (m_pointsCount > 0)
{
_SetUpCameraData();
DMatrix4x4 globalTLocal;
bool globalTLocalSuccess = m_tangoApplication.GetGlobalTLocal(out globalTLocal);
if (!globalTLocalSuccess)
{
return;
}
DMatrix4x4 unityWorldTGlobal = DMatrix4x4.FromMatrix4x4(TangoSupport.UNITY_WORLD_T_START_SERVICE) * globalTLocal.Inverse;
TangoPoseData poseData;
// Query pose to transform point cloud to world coordinates, here we are using the timestamp that we get from depth.
bool poseSuccess = _GetDevicePose(pointCloud.m_timestamp, out poseData);
if (!poseSuccess)
{
return;
}
DMatrix4x4 unityWorldTDevice = unityWorldTGlobal * DMatrix4x4.TR(poseData.translation, poseData.orientation);
// The transformation matrix that represents the point cloud's pose.
// Explanation:
// The point cloud, which is in Depth camera's frame, is put in Unity world's
// coordinate system(wrt Unity world).
// Then we are extracting the position and rotation from uwTuc matrix and applying it to
// the point cloud's transform.
DMatrix4x4 unityWorldTDepthCamera = unityWorldTDevice * m_deviceTDepthCamera;
transform.position = Vector3.zero;
transform.rotation = Quaternion.identity;
// Add offset to the point cloud depending on the offset from TangoDeltaPoseController.
if (m_tangoDeltaPoseController != null)
{
m_mostRecentUnityWorldTDepthCamera = m_tangoDeltaPoseController.UnityWorldOffset * unityWorldTDepthCamera.ToMatrix4x4();
}
else
{
m_mostRecentUnityWorldTDepthCamera = unityWorldTDepthCamera.ToMatrix4x4();
}
// Converting points array to world space.
m_overallZ = 0;
for (int i = 0; i < m_pointsCount; ++i)
{
Vector3 point = pointCloud[i];
m_points[i] = m_mostRecentUnityWorldTDepthCamera.MultiplyPoint3x4(point);
m_overallZ += point.z;
}
m_overallZ = m_overallZ / m_pointsCount;
m_depthTimestamp = pointCloud.m_timestamp; //m_timestamp is the time of capture of point cloud
// For debugging
if (m_updatePointsMesh)
{
// Need to update indices too!
int[] indices = new int[m_pointsCount];
for (int i = 0; i < m_pointsCount; ++i)
{
indices[i] = i;
}
m_mesh.Clear();
m_mesh.vertices = m_points;
m_mesh.SetIndices(indices, MeshTopology.Points, 0);
}
// The color should be pose relative; we need to store enough info to go back to pose values.
m_renderer.material.SetMatrix("depthCameraTUnityWorld", m_mostRecentUnityWorldTDepthCamera.inverse);
// Try to find the floor using this set of depth points if requested.
if (m_findFloorWithDepth)
{
_FindFloorWithDepth();
}
}
else
{
m_overallZ = 0;
}
I have tried to transform the touch positions from the screen space to the world space using Camera.main.ScreenToWorldPoint(). I have also tried to transform all point clouds from the world space to the screen space. The displayed point clouds and touch positions are the same on the screen but the transformed values are completely different.
Is there anyone knows this problem? Please help me. Thank you.
In TangoPointCloud.cs, m_points is populated with the latest point cloud in Unity world space. Consequently, the simplest way to determine whether points fall within a given portion of the screen is to use Unity's Camera.WorldToViewportPoint method to transform entries in m_points into viewport space (i.e. (0,0) is bottom left, and (1,1) is top right), and then check whether the given viewport point falls within your target area.
As an example, in the PointToPoint example that you mention, you could ignore all points that fall outside of the middle rectangle (i.e. half the width, half the height) of the screen by adding a simple check to _WaitForDepth before using the next selected point:
From PointToPointGUIController._WaitForDepth:
if (pointIndex > -1)
{
Vector3 screenPoint = cam.WorldToViewportPoint(
m_pointCloud.m_points[pointIndex]);
if (screenPoint.x > 0.25f && screenPoint.x < 0.75f &&
screenPoint.y > 0.25f && screenPoint.y < 0.75f) {
// Index is valid
m_startPoint = m_endPoint;
m_endPoint = m_pointCloud.m_points[pointIndex];
m_distance = Vector3.Distance(m_startPoint, m_endPoint);
}
}
Finally, to convert from Touch.position which is in screen space (i.e. pixels) to viewport space, you can use Camera.ScreenToViewportPoint, and then you can compare these directly with the viewport coordinates of a depth point.

Orientations Offset

I am using the MVN-Unity plug-in to access Xsens motion capture data and animate a Unity character in real-time. The character in white and green and yellow is a Unity skeleton that is animated based on Xsens motion data.
I am now trying to animate a different (non-Unity) character using Xsens (the other character that looks like a human) so similar to what the plug-in does, the motion data (positions & orientations) are being mapped to his joints/bones.
But as you can see below, something is wrong with orientations...
I think the reason might be that the rotations from MVN are not properly offset. As you can see in the next two pictures, the MVN hips have the x-axis (red) pointing to the puppet's backside, whereas for the guy's hips, the x-axis points to the right of him.
It might also be that the plug-in is using global rotations somewhere where it should use local rotations. That this must be the case can be demonstrated when I rotate the guy around before I start the Unity app; i.e. select the guy's root game object and try setting the y-rotation to 0/90/180/270 before pressing play, and compare the results: every time the distortions are different.
I don't know how to properly fix this. The code snippet that updates the Unity model (mapped to the MVN puppet or the guy) is as follows. I took this from the plug-in scripts:
private void updateModel(Transform[] pose, Transform[] model)
{
// Re-set the target, then set it up based on the segments.
Vector3 pelvisPos = new Vector3();
Vector3 lastPos = target.position;
target.position = Vector3.zero;
// Map only 23 joints.
for (int i = 0; i < 23; i++)
{
switch (i)
{
// Position only on y axis, and leave x and z to the body. Apply the 'global' position & orientation to the pelvis.
case (int)XsAnimationSegment.Pelvis:
pelvisPos = pose[i].position * scale;
model[i].position = new Vector3( model[i].position.x, pelvisPos.y, model[i].position.z );
model[i].rotation = pose[i].rotation * modelRotTP[i];
break;
// Update only the 'orientation' for the rest of the segments.
default:
if ( model[i] != null )
{
model[i].rotation = pose[i].rotation * modelRotTP[i];
}
break;
}
}
// Apply root motion if the flag is enabled; i.e. true.
if (applyRootMotion)
{
// Only update x and z, since pelvis is already modified by y previously.
target.position = new Vector3(pelvisPos.x + pelvisPosTP.x, lastPos.y, pelvisPos.z + pelvisPosTP.z);
}
// Set the final rotation of the full body, but only position it to face similar as the pelvis.
Quaternion q = Quaternion.Inverse(modelRotTP[(int)XsAnimationSegment.Pelvis]) * model[(int)XsAnimationSegment.Pelvis].rotation;
target.rotation = new Quaternion(target.rotation.x, q.y, target.rotation.z, target.rotation.w);
}
I sort of understand what the code does, but I don't know how to fix this problem. Most probably to do with the axes being different? I would appreciate any help...
You can modify XsLiveAnimator.cs script in the line: 496
with that
model[segmentOrder[i]].transform.rotation = orientations[segmentOrder[i]];
model[segmentOrder[i]].transform.Rotate(rotOffset, Space.World);
rotOffset is a Vector3 of your rotation

How to Calculate Target Destination

I'm having a bit of trouble figuring this one out. What I'm trying to achieve is a sort of tackling motion. The player lunges at the target from a distance.
The diagram shows the set up. The blue diamond is the player and the red thing is the target. The purple box is the renderer bounds of the targets SkinnedMeshRenderer. I'm using renderer bounds because some target's mesh are much larger than other. Currently, the player is shooting to the orange star...which is unrealistic. I want him to, no matter what way the target is facing, always target the closest point of the target relative to his position...in the diagram's case that would be the brown star. Here's the code I've been using...
public IEnumerator Blitz()
{
rigidbody.velocity = Vector3.zero; //ZERO OUT THE RIGIDBODY VELOCITY TO GET READY FOR THE BLITZ
SkinnedMeshRenderer image = target.GetComponentInChildren<SkinnedMeshRenderer>();
Vector3 position = image.renderer.bounds.center + image.renderer.bounds.extents;
position.y = target.transform.position.y;
while(Vector3.Distance(transform.position, position) > 0.5f)
{
transform.position = Vector3.Lerp(transform.position, position, Time.deltaTime * 10);
yield return null;
}
Results(); //IRRELEVANT TO THIS PROBLEM. THIS CALCULATES DAMAGE.
Blitz.Stop(); //THE PARTICLE EFFECT ASSOCIATED WITH THE BLITZ.
GetComponent<Animator>().SetBool(moveName, false); //TRANSITIONS OUT OF THE BLITZ ANIMATION
GetComponent<Input>().NotAttacking(); //LET'S THE INPUT SCRIPT KNOW THE PLAYER CAN HAVE CONTROL BACK.
}
//Get the derection to tarvel in and normalize it to length of 1
Vector3 Direction = (Target - transform.position).normalized
With Direction, you can do many things. For example, you can multiply the direction by your speed and add that to your position.
transform.position += Direction * MoveSpeed;
If you want to get to the closest point, you can use the handy Collider.ClosestPointOnBounds method.
Target = TargetObject.GetComponent<Collider>().ClosestPointOnBounds(transform.position)
and plug the Target into the code used to get the direction.
Alternatively, you can use Vector3.Lerp without getting a direction since it's just interpolating.
transform.position = Vector3.Lerp(Target,transform.position,time.DeltaTime);
For stopping at the target point, you can use the arrival behavior.
//Declare the distance to start slowing down
float ClosingDistance = Speed * 2;
//Get the distance to the target
float Distance = (Target - transform.position).magnitude;
//Check if the player needs to slow down
if (Distance < ClosingDistance)
{
//If you're closer than the ClosingDistance, move slower
transform.position += Direction * (MoveSpeed * Distance / ClosingDistance);
}
else{
//If not, move at normal speed
transform.position += Directino * MoveSpeed;
}

How to prevent colliders from passing through each other?

I am having trouble keeping game objects inside of a contained space. When they reach the edge, there is some momentary push back but then they will go right through the wall.
I am using a Box Collider on the player, and a Mesh Collider for the level's wall. I am having issues with both a Player Character (a space ship) that the movement is controlled by the player. And with projectiles, which are fire and forget moving at a constant speed.
This is my movement code for my player. It is being run in the FixedUpdate() function.
//Movement
haxis = Input.GetAxis("Horizontal") * speed;
vaxis = Input.GetAxis("Vertical") * speed;
moveVector.x = haxis;
moveVector.z = vaxis;
if(moveVector.magnitude > 1)
{
moveVector.Normalize();
}
rigidbody.MovePosition(transform.position + moveVector * speed);
With the bullets, they are given a velocity and the engine calculates their moviements. They are using Box Collider and it is set as a Trigger so they don't have physics. But I use OnTriggerEnter to destroy them.
//Projectiles without physics collisiions
function OnTriggerEnter (other : Collider) {
Destroy(gameObject);
}
Some, but not all of the bullets will be destroyed when hitting the mesh collider wall. The player will sometimes hit it and stop, but can usually push through it. How can I make the collisions with the mesh collider work every time?
Collision with fast-moving objects is always a problem. A good way to ensure that you detect all collision is to use Raycasting instead of relying on the physics simulation. This works well for bullets or small objects, but will not produce good results for large objects.
http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html
Pseudo-codeish (I don't have code-completion here and a poor memory):
void FixedUpdate()
{
Vector3 direction = new Vector3(transform.position - lastPosition);
Ray ray = new Ray(lastPosition, direction);
RaycastHit hit;
if (Physics.Raycast(ray, hit, direction.magnitude))
{
// Do something if hit
}
this.lastPosition = transform.position;
}
I have a pinball prototype that also gave me much trouble in the same areas. These are all the steps I've taken to almost (but not yet entirely) solve these problems:
For fast moving objects:
Set the rigidbody's Interpolate to 'Interpolate' (this does not affect the actual physics simulation, but updates the rendering of the object properly - use this only on important objects from a rendering point of view, like the player, or a pinball, but not for projectiles)
Set Collision Detection to Continuous Dynamic
Attach the script DontGoThroughThings (https://www.auto.tuwien.ac.at/wordpress/?p=260) to your object. This script cleverly uses the Raycasting solution I posted in my other answer to pull back offending objects to before the collision points.
In Edit -> Project Settings -> Physics:
Set Min Penetration for Penalty to a very low value. I've set mine to 0.001
Set Solver Iteration Count to a higher value. I've set mine to 50, but you can probably do ok with much less.
All that is going to have a penalty in performace, but that's unavoidable. The defaults values are soft on performance but are not really intented for proper simulation of small and fast-moving objects.
How about set the Collision Detection of rigidbody to Continuous or Continuous Dynamic?
http://unity3d.com/support/documentation/Components/class-Rigidbody.html
So I haven't been able to get the Mesh Colliders to work. I created a composite collider using simple box colliders and it worked exactly as expected.
Other tests with simple Mesh Colliders have come out the same.
It looks like the best answer is to build a composite collider out of simple box/sphere colliders.
For my specific case I wrote a Wizard that creates a Pipe shaped compound collider.
#script AddComponentMenu("Colliders/Pipe Collider");
class WizardCreatePipeCollider extends ScriptableWizard
{
public var outterRadius : float = 200;
public var innerRadius : float = 190;
public var sections : int = 12;
public var height : float = 20;
#MenuItem("GameObject/Colliders/Create Pipe Collider")
static function CreateWizard()
{
ScriptableWizard.DisplayWizard.<WizardCreatePipeCollider>("Create Pipe Collider");
}
public function OnWizardUpdate() {
helpString = "Creates a Pipe Collider";
}
public function OnWizardCreate() {
var theta : float = 360f / sections;
var width : float = outterRadius - innerRadius;
var sectionLength : float = 2 * outterRadius * Mathf.Sin((theta / 2) * Mathf.Deg2Rad);
var container : GameObject = new GameObject("Pipe Collider");
var section : GameObject;
var sectionCollider : GameObject;
var boxCollider : BoxCollider;
for(var i = 0; i < sections; i++)
{
section = new GameObject("Section " + (i + 1));
sectionCollider = new GameObject("SectionCollider " + (i + 1));
section.transform.parent = container.transform;
sectionCollider.transform.parent = section.transform;
section.transform.localPosition = Vector3.zero;
section.transform.localRotation.eulerAngles.y = i * theta;
boxCollider = sectionCollider.AddComponent.<BoxCollider>();
boxCollider.center = Vector3.zero;
boxCollider.size = new Vector3(width, height, sectionLength);
sectionCollider.transform.localPosition = new Vector3(innerRadius + (width / 2), 0, 0);
}
}
}
1.) Never use MESH COLLIDER. Use combination of box and capsule collider.
2.) Check constraints in RigidBody. If you tick Freeze Position X than it will pass through the object on the X axis. (Same for y axis).
Old Question but maybe it helps someone.
Go to Project settings > Time and Try dividing the fixed timestep and maximum allowed timestep by two or by four.
I had the problem that my player was able to squeeze through openings smaller than the players collider and that solved it. It also helps with stopping fast moving objects.
Edit ---> Project Settings ---> Time ... decrease "Fixed Timestep" value .. This will solve the problem but it can affect performance negatively.
Another solution is could be calculate the coordinates (for example, you have a ball and wall. Ball will hit to wall. So calculate coordinates of wall and set hitting process according these cordinates )
Try setting the models to environment and static. That fix my issue.