Unity spawning lots of objects at runtime running slow - unity3d

I've created a simple project where approx. 7000 cubes are created in the scene (with VR camera) but the problem is that when I move camera to see all cubes the FPS becomes very bad, something like 5-6 frames. My PC is i7 with GTX 1070, and I thought that it have to draw hundred thousands of cubes without any problems. Really, I saw minecraft, it looks like there no problems to draw cubes ))
So question is is it possible to optimize the scene so that all cubes are painted it one call or something to provide a good performance?
I'm actually made all cubes static and there are no textures only standard material...
Here is how it looks now:
I'm using default Directional Light and It would be good to not change the standard shader because of it great work with light.
Here is how I'm generating the cubes:
private void AddCube(Vector3 coords)
{
var particle = (Transform)MonoBehaviour.Instantiate(prototype.transform, holder.transform);
SetScale(particle);
SetPosition(particle, coords);
cubes.Add(particle.gameObject);
particle.gameObject.isStatic = true;
}
private void SetScale(Transform particle)
{
particle.localScale = new Vector3(Scale, Scale, Scale);
}
private void SetPosition(Transform particle, Vector3 coords)
{
particle.position = coords;
}
This is the screenshot of Stats:
I have here 41 fps because I moved camera away from cubes to have clean background for the stats panel. Actually after I'm making the cubes 'static' the FPS is depends on are the cubes visible on the screen or not.

The problem is most likely caused by number of individual objects you are instantiating. If cubes doesnt change their transform after generating you should be able to use StaticBatchingUtility to combine them into one batch.
Call this after generating cubes.
StaticBatchingUtility.Combine(GameObject cubesRoot);

Related

How could I create a copy of a gameobject hierachy which mimics all positions, movements, etc of the original? Like a hologram of the original?

I am building a 3d Billiard game in VR using Unity3d.
I try to display a miniature copy of the billiard "table" (actually a cube), like it is at any given moment.
I tried instantiating the root of the billiard hierarchy, just to find out it will instantiate the original gameObject (runnings its Start() methods) which totally makes sense, just not what i am trying to do.
In practice I have a billiard root, which has all the geometry of the table, and all balls as children, those balls can interact physically.
On button press I try to create a hologram of the table, with all its balls at their position at any given time.
So If a player hits a ball and it moves in the original, it should display the same in the miniature.
I thought it might be possible to translate the ball positions (and table rotation etc) every frame to the miniature. but that seams very un optimal.
var midPoint = (leftHand.transform.position + rightHand.transform.position) / 2;
var miniature = Instantiate(gameObject, midPoint, transform.rotation);
miniature.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
this obviously does not work as i described above. It creates a completely new instance of the billiard cube. (this code was run from a script inside the billiard root)
The board itself probably doesn't move, so you can just make holograms and simulate the balls.
Since Unity 2018.2, you can create physics scenes and simulate them manually.
For that problem you would need to:
Stop physics simulations.
Physics.autoSimulation = false;
Create a new scene for independent physics simulation.
var physicsPreviewScene = SceneManager.CreateScene("Physics Preview Scene", sceneParams);
Copy the physics-relevant objects and components to the preview scene.
Many ways to do it, but basically colliders, rigidbodies, and for objects you need visuals for, renderers.
You can use caching to avoid creating these every time.
You can also, in theory, have the simulation on the main scene, but then you need to make kinematic all the stuff you don't want simulated, and there are some gotchas.
Then simulate manually.
Get the PhysicsScene from the preview scene: var physicsScene = physicsPreviewScene.GetPhysicsScene();
Simulate: physicsScene.Simulate();
So yea, short of avoiding the components unrelated to physics in the copies, you can't avoid the duplicates; only mitigate their impact with pooling and/or caching.
Another technique is to use casting (spherecasting, in this case) to make a mockup physics simulation, stepping multiple casts with velocity, acceleration (gravity for example) and Time.fixedDeltaTime, and reacting to intercepts/hits as collisions, with Vector3.Reflector something similar. But this will only give you an approximation of how physics would react, and is not going to be an actual (accurate) physics simulation like having multiple PhysicsScenes will.

Unity and VR for complex construction CAD models

I work in construction and we are trying to visualize our projects using Unity and Oculus Rift.
Basically all our models are created using Revit and we export them out to fbx and bring them into Unity. For each model we have (electrical, mechanical, architectural, facade...) we generate a fbx in Revit and bring into Unity.
The models have around 3000 to 60000 objects(meshes) and around 3 million to 40 million polygons. When we try to visualize the models in Unity we are getting very low FPS, around 2 to 3 fps, and batch draw calls around 15000 to 20000.
I believe the problem is the complexity of all our models that we bring together into Unity. I wonder if there is any way to optimize it, I already tried decimating, disabling shadows, occlusion but nothing seems to work. Collapsing the models into a single object is not an option because we have to allow the user to select and inspect individual elements.
I am working on something similar and i can share some experiences for tasks like this with many vertices or meshes. I am trying to visualize point clouds in Unity and it is a very challenging task. In my case though i create point clouds myself and i do not triangulate them. It helps but i still have to apply optimizations.
From my experience if you have vertices more than 10 million rendered at a frame you start to have fps issues. This can vary based on your hardware of course. Also i am sure this will be even worse with triangulated meshes. What i have done to optimize things are following:
I first started by rendering objects that are in Camera Frustum In order to do this i used a function called IsVisibleFrom which is an extension to Renderer like this:
using UnityEngine;
public static class RendererExtensions
{
public static bool IsVisibleFrom(this Renderer renderer, Camera camera)
{
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
}
}
Then you can use it like this by traversing all the meshes you have:
Renderer grid;
IEnumerator RenderVisibleGameObject()
{
for (int i = 0; i < PointCloud.transform.childCount; i++)
{
grid = PointCloud.transform.GetChild(i).GetComponent<Renderer>();
if (!grid.IsVisibleFrom(cam))
{
grid.gameObject.SetActive(false);
}
else
{
grid.gameObject.SetActive(true);
}
if (i == (PointCloud.transform.childCount - 1))
yield return null;
}
StartCoroutine(RenderVisibleGameObject());
}
Second option would be if possible and if you can create meshes with lower detail using Level of Detail. Basically what it does is rendering low detail meshes that are further away from camera.
Last option i can recommend is using Occlusion Culling. This is similar to first option but it also takes care of occlusions which was not the case for me because i had only points.
You may also find the Forge Unity AR/VR toolkit of interest:
Overview
Introduction
23-minute video
As you probably know, Forge is highly optimised for professional visualisation of large CAD models.

Connecting Game Objects to a pane from a spawner in Unity?

I have a pane with one cube on it with a spawner which will spawn cubes out when the game is played. The pane can be rotated and the cubes should stick to it and move forward.
The part i am stuck on is making the cubes that come from the spawner to stick.
I managed to make the original cube stick using
Object1.transform.parent = Object2.transform;
I also managed to make the spawner stick to the pane using the same method.
However when i use this the first cube will stick fine and the cubes from the spawner are not showing up. From what i have researched it could be a scaling issue. Also the spawned cubes do appear under the cube as "Cube(clone)" but their scale is diffrent to the original cube. I have also noticed the scale of the original Cube changes when i press play. It goes from - (10,10,10) to float numbers.
A solution i tried was to set the scale but when i done this the objects did not stick on to the pane at all.
However they did spawn normally.Using this method.
void Update () {
Vector3 scale = new Vector3(10, 10, 10);
Object1.transform.localScale = scale;
Object1.transform.parent = Object2.transform;
}
If anyone has any ideas it will be much appreciated.
In situations like this, it's quite often best to parent an object first, then deal with the local transformations. Local transformations such as transform.localPosition, transform.localRotation and transform.localScale deal with the object's local values in relation to the parent.
There's a paragraph at the end of this page that describes it well:
Note that the parent transform's world rotation and scale are applied
to the local position when calculating the world position. This means
that while 1 unit in Transform.position is always 1 unit, 1 unit in
Transform.localPosition will get scaled by the scale of all ancestors.

Unity3d - Need to hide a group of objects in the area

I've already tried depthmask shaders and examined some other ideas, but it seems like it doesn't suit me at all.
I'm making an AR game and I have a scene with a house and trees. All these objects are animated and do something like falling from the sky, but not all at once, but in sequence. For example, the house first, then trees, then fence etc.
(Plz, look at my picture for details) http://f2.s.qip.ru/bVqSAgcy.png
If user moves camera too far, he will see all these objects stucking in the air and waiting for their order to start falling, and it is not good. I want to hide this area from all sides (because in AR camera can move around freely) and make all parts visible only when each will start moving (falling down).
(One more screen) http://f3.s.qip.ru/bVqSAgcz.png
I thought about animation events, but there are too many objects (bricks, for example) and I can't handle all of them manually.
I look forward to your great advice ;)
P.S. Sorry for my bad english.
You can disable their(the objects that are gonna fall) mesh renderers and re active them when they are ready to fall.
See here for more details about mesh renderer.
Deactivate your Object. You might use the camera viewport coordinates to get a y position outside the viewport. They start on the bottom left of the screen (0,0) and go to the top right of the screen (1,1). Convert them to worldspace coordinates. Camera.ViewportToWorldPoint
Vector3 outsideCamera = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 1.2f, 10.0f));
Now you can use the intended x and z positions of your object. Activate it when you want to drop it.
myObject.transform.position = new Vector3(myObject.transform.position.x, outsideCamera.y, myObject.transform.position.z);
Another thing you could additionally do is scaling the object from very small to its intended size when it is falling. This would prevent the object being visible before falling when the users point the camera upwards.
1- Maybe you can use the Camera far clipping plane property.
Or you can even use 2 Cameras if you need to display let's say the landscape on one (which will not render the house + trees + ...) with a "big" far clipping plane and use a second one with Depth only clear flags rendering only the items (this one can have a smaller far clipping plane from what I understand).
2- Other suggestion I'd give you is adding the scale to your animation:
set the scale to 0 on the beginning of animation
wait for the item to be needed to fall down
set the scale to 1 (with a transition if needed)
make the item fall down
EDIT: the workaround you found is quite just fine too! But tracking only world position should be enough I think (saving a tiny amount of memory).
Hope this helps,
Finally, the solution I chose. I've added this script to each object in composition. It stores object's position (in my case both world and local) at Start() and listening if it changes in Update(). So, if true, stop monitoring and set MeshRenderer in on state.
[RequireComponent(typeof(MeshRenderer))]
public class RenderScript : MonoBehaviour
{
private MeshRenderer mr;
private bool monitoring = true;
private Vector3 posLocal;
private Vector3 posWorld;
// Use this for initialization
void Start()
{
mr = GetComponent<MeshRenderer>();
mr.enabled = false;
posLocal = transform.localPosition;
posWorld = transform.position;
}
// Update is called once per frame
void Update()
{
if (monitoring)
{
if (transform.localPosition != posLocal || transform.position != posWorld)
{
monitoring = false;
mr.enabled = true;
}
}
}
}
Even my funny cheap сhinese smartphone is alive after this, so, I guess, it's OK.

Wheel Collider Unity: after adding torque the vehicle starts moving sideways

I really killed few hours to try to fix this, Googling for a solution, but I could not.
I've got a vehicle, it's a go-cart, so there are no suspensions (technically there are, but the values are close to 0, to simulate the tires). The vehicle has a rigid body attached and the child object contains the 4 wheel colliders (and the model itself), as can be seen here:
https://dl.dropboxusercontent.com/u/76599014/sxc/Clipboard01.jpg
For testing, I added a short script to make the vehicle move. It's in the GameObject called "gokart":
public class carControler : MonoBehaviour {
public WheelCollider fr, fl, rr, rl;
public float performance = 50f;
void FixedUpdate () {
throttle();
}
public void throttle() {
this.rl.motorTorque = this.performance;
this.rr.motorTorque = this.performance;
} }
What happens is: the rear wheels start to rotate, as intended, but the vehicle starts moving sideways slowly. The movement speed depends on the torque amount (the wheel rotation in this case). There is no movement forward, so this is not the bug, where when you are standing on a flat surface you are drifting on the sides.
Any ideas? If you need a video or a GIF (I have to figure out how to make one) of the movement, I'll be glad to provide one.
I think you should try and apply 0 brake torque to the front wheels while applying motor torque to the rear wheels.
public void throttle() {
this.rl.motorTorque = this.performance;
this.rr.motorTorque = this.performance;
this.fr.brakeTorque = 0f;
this.fl.brakeTorque = 0f;
}
That being said, anything could go wrong if the Rigidbody/wheelcolliders aren't set up correctly. Unity's wheel colliders can be difficult to set up and work with. Unity changed the physics in Unity 5 so most documentations are outdated.
I found this very good short document that was made by unity: http://unity3d.com/profiles/unity3d/themes/unity/resources/downloads/beta/unity-5.0-user-guide.pdf
It highlights the changes that was made to unity 5 and at the end of page 5 you can find a section that explains how to set up a car. I have tried it about a month ago in a new unity project and it worked. the instructions are clear so try this tutorial out and I hope it will help.
Regards
Not having the image available I'm not a totally sure about the situation but my assumption based on your description is you should try increasing the sideways friction and tweak the forward friction a little bit according to your taste. You have to increase the sideways friction anyways as you are making a go-cart. As far as I know, most arcadey go-carts don't drift and behave a lot different from regular racing cars.
Hope that will solve the problem.