Hello!
In my game, I need to create the mechanics of the shot as accurately as possible. I think that the best way is to release the bullet as a rigid body with the impulse applied to it (ForceMode.Impulse). But I also sometimes need to release bullets very often - every 0.1 sec. This leads to a decrease in the FPS.
I already tried to do this with a raycast, but this does not work in case you need to shoot ahead.
What other ways are there to implement this mechanics? Or have I misconfigured physics? Any ideas.
After reading the recommendations in the comments, I made some changes to the code. I brought the variables out of the body of the function and measured the time of the Fire () method using StopWatch. The method is executed on average 0.2 ms.
I also measured the execution time of the OnCollisionEnter(). It executes in an average of 0.2 ms, but very often it happens in 4-6 ms.
Here’s what the profiler looks like when nothing happens in the game
Spines all the time arise on different methods: PxsMBP.updateWork, PxsContext.mergeCMDescreteResults, ScSceneAfterInegrations, updateCCDMultiPass, Pxs.MBP.postUpdateWork.
@EvgenFree
The only improvements according to my knowledge are
1.)predefine new Vector3(0,0,0)in both the lines and use the variable instead i.e.,
do this before start() Vector _emptyVector=new Vector3(0,0,0) and use _emptyVector variable where ever you need.
2.)Try to increase physics time step in settings according to your needs without losing quality of game mechanics
you told raycasting is not working to shoot ahead,I don’t understand what you are saying exactly but
If you want to detect collisions behind walls like that setup a Layer for your hittable objects and use it
you have a huuuuge garbage collection. Use a pool for the bullets. Instantiate them at the beginning of the scene then just call them when the gun shoots. then when they hit the target(or fly to far) set them back false and send them to the pool again.
Here is a pooler i builkt and use for all my games.
Create an empty object in the scene and call it Pools (or something)
create a new C# script called LevelPools(or something)
create a new c# script called projectiles(or something)
create a new c# script called ObjectPooler(or something)
inside the projectiles class you will instatiate a new objectpooler for each type of bullet you want.
build the pools
then have a get method to retrieve it.
[Serializable]
public class Projectiles
{
public ObjectPooler bullet50Cal = new ObjectPooler();
public void BuildAllPools()
{
bullet50Cal.BuildPool();
}
public GameObject GetProjectile(ObjectPooler projectile) => projectile.GetClone();
}
Inside the object pooler you will actually build the pool from a list of gameobjects it gets from inspector fields. create a folder to put the object, a prefab for the object, and tell it how many to spawn
`
using System.Collections.Generic;
using UnityEngine;
using System;
[Serializable]
public class ObjectPooler
{
[Tooltip(“The folder that the clones will be placed into.”)]
public Transform cloneFolder = null;
[Tooltip(“The object that will be spawned.”)]
public GameObject objectToClone = null;
[Tooltip(“The number of clones that will be created.”)]
public int numberOfEachToSpawn = 100;
[HideInInspector]
public List objectPool = new List();
// Have the pools been built
bool poolsBuilt = false;
// Create a pool of an object.
// This will clone the objectToClone by numberOfEachToSpawn times.
// The clones will be placed inside the cloneFolder and set inactive.
public void BuildPool()
{
for (int i = 0; i < numberOfEachToSpawn; i++)
{
GameObject projectileClone;
if (cloneFolder != null)
projectileClone = MonoBehaviour.Instantiate(objectToClone, cloneFolder);
else
projectileClone = MonoBehaviour.Instantiate(objectToClone);
projectileClone.SetActive(false);
objectPool.Add(projectileClone);
}
poolsBuilt = true;
}
// Grabs a clone from the pool and returns it to the method that calls this.
public GameObject GetClone()
{
if (poolsBuilt)
{
for (int i = 0; i < numberOfEachToSpawn; i++)
{
if (!objectPool*.gameObject.activeInHierarchy)* { return objectPool*;* } } } else Debug.Log(“Need To Build The Object Pool On Awake”); return null; } }` Finnaly in the level pools script this will all come together. you will instiate a projectile class that houses the bullets build all the pools for the projectiles. then have a Get method that grabs the inactive projectile that you call from the weapon script. So instead of calling Instantiate(prefab); you call GameObject clone = levelPools.Get50CalBullet(); clone.transform.SetPositionAndRotation(barrelEnd.position,barrelEnd.rotation); clone.SetActive(true); then add the force to it on the projectile add a OnCollisionEnter or raycast that will set it inactive on colllision or detection. Here is the LevelPool public class LevelPools : MonoBehaviour { public Projectiles projectiles = new Projectiles();
#region Bullet projectiles // Bullets public GameObject Get50CalBullet() => projectiles.GetProjectile(projectiles.bullet50Cal); // Create all the rest of the bullets calls here #endregion } using this same setup in the same level pools you can build classes for muzzle flashes, impacts,… everything you want. just create the class just like the Projectiles class.