Technical Review
Gravity Ruckus
Philipp Welsch, Philipp Wimmer,
Lukas Rosenberger
Pooling
Most weapons are projectile based -> Lots of GameObjects in play at once.
Continously deleting and allocating projectiles would be terrible for performance.
GC considered harmful.
Alternative: Allocate all memory upfront and only reuse.
Pooling - ObjectPool
Encapsuates a List of PooledGameObject.
Ctor is passed size of pool and allocates accordingly.
Also supports Allocate(int), however this is never used.
Internally uses CircularListIterator to keep moving through pool and find unused object.
If all instances are in use, null is returned.
Pooling - PooledGameObject
Two approaches:
Be intrusive and add PoolingComponent to GameObject
or
Encapsulate GameObject and move all pool operations into owner class
Pooling - PooledGameObject
Two approaches:
or
Keep internals of GameObject and pooling seperate.
Different GOs have different state, needs to be reset accordingly.
ResetComponent is used to reset state.
Encapsulate GameObject and move all pool operations into owner class
Be intrusive and add PoolingComponent to GameObject
Pooling - PooledGameObject
Request() changes the object to owned.
Instance is used to access the internal GameObject.
Release() resets the object and clears it for reacquisition.
Also calls each ResetComponent.
{
"Prefabs": [
[ "Prefab/SphereProjectile", 30 ],
[ "Prefab/BounceProjectile", 180 ],
[ "Prefab/GravityProjectile", 60],
[ "Prefab/BlobProjectile", 60 ],
[ "Prefab/UltimateProjectile", 4 ]
],
"Usage": [
"This file defines the path to all GameObject prefabs which should",
"have GoPools created for them on startup.",
"[Path, Instances]",
"Path: A string that defines the prefabs location relative to Assets/.",
"Instances: An integer that defines the amount of Prefab ",
"instances that should be allocated.",
"This may be omitted. In this case, 8 instances will be allocated."
]
}
Pooling - JSON
Pooling - GameObjectPoolManager
Reads the config file and creates the pools from it.
Stores a collection of GameObjectPools.
Requests are issued using the prefab:
Request(GameObject prefab)
Exists(GameObject prefab)
Allocate(GameObject prefab)
GetNumInstances(GameObject prefab)
Reset() needs to be called when changing scenes, as Unity kills all GameObjects in a scene.
Gravity
Dynamic gravity switching based on proximity didn't work out
- Unexpected behaviour for the player
- Calculating the proper rotations in 3D very hard
- Pretty resource-intensive (OverlapSphere every frame)
Switching gravity based on player input (gravity switch button) proved to be less confusing and easier to execute.
Gravity
Basic execution order for a gravity switch:
- Query player input
- Calculate a new Gravity Vector
- Set Switch Vector (local Rotation)
- Normalize local Rotation
- Calculate New Rotation
- Set new Gravity
- Notify Gravity Observers (Gravity Launcher)
FixedUpdate:
- Add Current Gravity via RigidBody.AddForce with ForceMode Acceleration
- Finish gravity rotations
void FixedUpdate()
{
m_rigidBody.AddForce(m_gravityVec*100, ForceMode.Acceleration);
if (m_fRotationTime <= 1.1f)
{
transform.localRotation = Quaternion.Slerp(m_quatOldRotation, m_quatNewRotation, m_fRotationTime);
m_fRotationTime += 0.1f;
}
}
Using Quaternion.Slerp with the old Rotation effectively locks the player into the rotation for its duration.
Since its only 10 fixedUpdate frames (=0.2 seconds) it's not really noticeable.
It also prevents the rotation from going wrong and the player 'tilting'.
Input - First Attempt
Using Unitys built in input manager and set the bindings in the editor.
This turned out to cause massive problems when more than one controler was plugged in.
- Different controlers would have different layouts
- Sometimes the controls would not work at all or cause random behaviour.
Input - Second Attempt
Write our own input handler and set the bindings via a JSON file to remain flexible.
Use XboxCtrlrInput(XCI) as a wrapper, since it handles multiple controlers well and is easy to use.
The bindings are stored in three dictionaries (Axis, Buttons, DPad) within the players PlayerInput class.
A reference to the PlayerInput class is then used to get the abstracted Input.
Code Review
By Philipp Welsch
Code Review
- 1,326