I am a bit unsure as to what people generally find proper in regards to where you declare your variables as well as how many parameters you use.
Generally, I like to have most if not all of my variables placed on top in the class so that I can see them all. I would declare iterator variables for loops and such usually at the loop, as well as any variable that I know I will just need temporarily for 1 method to run at Awake() or something closer to its scope.
Let me give an example. Here is my OverlapCapsule method.
using UnityEngine;
using System.Collections;
public partial class ExtensionsPhysics
{
static Collider[] colliderArray;
static Collider[][] colliderArrays;
public static Collider[] OverlapCapsule(Vector3 position, Vector3 directionUp, float height, float radius)
{
LayerMask mask = Physics.AllLayers;
return OverlapCapsule(position, directionUp, height, radius, mask);
}
public static Collider[] OverlapCapsule(Vector3 position, Vector3 directionUp, float height, float radius, LayerMask mask)
{
float capsuleBottomTopDistanceToCenter = radius * (((height / 2) / radius) - 1);
Vector3 capsuelBottomPosition = position - (directionUp * capsuleBottomTopDistanceToCenter);
Vector3 capsuelTopPosition = position + (directionUp * capsuleBottomTopDistanceToCenter);
if(!Physics.CheckCapsule(capsuelBottomPosition, capsuelTopPosition, radius, mask)) return null;
int overlapSphereCount = Mathf.CeilToInt(((height / radius) - 1));
float overlapShereMoveDistance = (capsuleBottomTopDistanceToCenter * 2) / overlapSphereCount;
colliderArrays = new Collider[overlapSphereCount+1][];
for(int i=0;i<colliderArrays.Length;i++)
{
colliderArrays[i] = Physics.OverlapSphere(capsuelBottomPosition, radius, mask);
capsuelBottomPosition += (directionUp * overlapShereMoveDistance);
}
return CleanUpArrays();
}
static Collider[] CleanUpArrays()
{
//will put in remove duplicate method later
colliderArray = new Collider[GetMultiArrayLength.GetJaggedArrayLength<Collider>(colliderArrays)];
int count = 0;
for(int i=0;i<colliderArrays.Length;i++)
{
for(int j=0;j<colliderArrays[i].Length;j++)
{
colliderArray[count] = colliderArrays[i][j];
count++;
}
}
return colliderArray;
}
}
Usually when it comes to static classes I would declare the variable close to its scope because static scares me or something, but you can see on top I have declared 2 Collider arrays. I have done this because I have read that parameters should be avoided, so instead of declaring these collider arrays close to scope and then passing them as a parameter to the “CleanUpArray” method, I just declared them at the highest scope. Is this the proper way to do things?
(Side question - When I do colliderArray = new Collider[“number here”][ ] what happens to the old array? Is this now going to garbage collection? Wouldn’t avoiding garbage collection be best? Should I be clearing this array and reusing it? How does unity do it with their OverlapSphere and such? Whenever I have an array in a loop, I don’t want to declare it close to scope. I feel like having it declared at top and created in a start() function or something and then just using it, instead of recreating over and over, especially if it will be large.)
Here is another script which would give you a better example of how I do things.
using UnityEngine;
using System.Collections;
public class GetCastsCenterOnCollision
{
float capsuleCastStartPointHitPointDistance;
float bottomPointHitPointDistance;
float topPointHitPointDistance;
float startPointHitPointHeight;
float capsuleCastHeight;
float capsuleHeightRadiusDifference;
float capsuleCastCenterHitPointOffsetDistance;
float sphereCastStartPointHitPointDistance;
Vector3 capsuleCastStartPointCenter;
Vector3 storedCapsuleCastStartPointCenter;
Vector3 capsuleCastBottomTopPointDirection;
Vector3 startPointHitPointDirection;
Vector3 capsuleCastEndPoint;
Vector3 startPointHitPointHorizontalAlignedPoint;
Vector3 capsuleCastCenter;
Vector3 capsuleCastCenterFlatBottom;
Vector3 sphereCastEndPoint;
Vector3 sphereCastCenter;
SphereLineIntersect sphereLineIntersect = new SphereLineIntersect();
MyVector3CrossMethods myVector3CrossMethods = new MyVector3CrossMethods();
public Vector3 GetCapsuleCastCenterOnCollision(Vector3 capsuleCastBottomPoint, Vector3 capsuleCastTopPoint, float capsuleCastRadius, Vector3 capsuleCastDirection, Vector3 capsuleCastHitPoint)
{
capsuleCastStartPointCenter = (capsuleCastBottomPoint / 2) + (capsuleCastTopPoint / 2);
storedCapsuleCastStartPointCenter = capsuleCastStartPointCenter;
capsuleCastBottomTopPointDirection = (capsuleCastBottomPoint - capsuleCastTopPoint).normalized;
capsuleCastStartPointHitPointDistance = Vector3.Distance(capsuleCastStartPointCenter, capsuleCastHitPoint);
bottomPointHitPointDistance = Vector3.Distance(capsuleCastBottomPoint, capsuleCastHitPoint);
topPointHitPointDistance = Vector3.Distance(capsuleCastTopPoint, capsuleCastHitPoint);
capsuleCastEndPoint = capsuleCastStartPointCenter + (capsuleCastDirection * capsuleCastStartPointHitPointDistance);
startPointHitPointHorizontalAlignedPoint = myVector3CrossMethods.GetVector3CrossPosition(capsuleCastStartPointCenter, capsuleCastHitPoint, capsuleCastBottomTopPointDirection);
startPointHitPointHeight = Vector3.Distance(startPointHitPointHorizontalAlignedPoint, capsuleCastHitPoint);
capsuleCastHeight = Vector3.Distance(capsuleCastBottomPoint,capsuleCastTopPoint) + (capsuleCastRadius * 2);
capsuleHeightRadiusDifference = (capsuleCastHeight / 2) - capsuleCastRadius;
if(startPointHitPointHeight > capsuleHeightRadiusDifference)
{
if(bottomPointHitPointDistance < topPointHitPointDistance)
{
capsuleCastStartPointCenter += capsuleCastBottomTopPointDirection * capsuleHeightRadiusDifference;
capsuleCastEndPoint += capsuleCastBottomTopPointDirection * capsuleHeightRadiusDifference;
}else{
capsuleCastStartPointCenter -= capsuleCastBottomTopPointDirection * capsuleHeightRadiusDifference;
capsuleCastEndPoint -= capsuleCastBottomTopPointDirection * capsuleHeightRadiusDifference;
}
}else if(bottomPointHitPointDistance < topPointHitPointDistance)
{
capsuleCastStartPointCenter += capsuleCastBottomTopPointDirection * startPointHitPointHeight;
capsuleCastEndPoint += capsuleCastBottomTopPointDirection * startPointHitPointHeight;
}else{
capsuleCastStartPointCenter -= capsuleCastBottomTopPointDirection * startPointHitPointHeight;
capsuleCastEndPoint -= capsuleCastBottomTopPointDirection * startPointHitPointHeight;
}
capsuleCastCenter = sphereLineIntersect.GetSphereLineIntersect(capsuleCastStartPointCenter, capsuleCastEndPoint, capsuleCastHitPoint, capsuleCastRadius);
capsuleCastCenter = storedCapsuleCastStartPointCenter + capsuleCastCenter;
return capsuleCastCenter;
}
public Vector3 GetSphereCastCenterOnCollision(Vector3 sphereCastOrigin, float sphereCastRadius, Vector3 sphereCastDirection, Vector3 sphereCastHitPoint)
{
sphereCastStartPointHitPointDistance = Vector3.Distance(sphereCastOrigin, sphereCastHitPoint);
sphereCastEndPoint = sphereCastOrigin + (sphereCastDirection * sphereCastStartPointHitPointDistance);
sphereCastCenter = sphereLineIntersect.GetSphereLineIntersect(sphereCastOrigin, sphereCastEndPoint, sphereCastHitPoint, sphereCastRadius);
sphereCastCenter = sphereCastOrigin + sphereCastCenter;
return sphereCastCenter;
}
}
As you can see, I declared many variables on top.
When people say parameters are bad, do they mean parameters within the method, for example, a helper method within the class shouldnt have parameters? Or do they mean the actual method itself should not really have parameters. If so, then how would you give info to the methods to do stuff, especially if the info keeps changing every frame? I really don’t know what they mean by avoiding parameters. Plenty of unitys methods have many parameters. Should many parameters only be used for static methods or something?
Please let me know how you or most people may generally do things, as well as reasons why. What is it that I am doing might be wrong or cause trouble in the future?
I know the saying “premature optimization is the root of all evil”, the problem is that I don’t know enough to know if I am over optimizing.
edit - my end result for the OverlapCapsule method
OverlapCapsule
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public partial class ExtensionsPhysics
{
public static Collider[] OverlapCapsule(Vector3 position, Vector3 directionUp, float height, float radius)
{
LayerMask mask = Physics.AllLayers;
return OverlapCapsule(position, directionUp, height, radius, mask);
}
public static Collider[] OverlapCapsule(Vector3 position, Vector3 directionUp, float height, float radius, LayerMask mask)
{
float capsuleBottomTopDistanceToCenter = radius * (((height / 2) / radius) - 1);
Vector3 capsuelBottomPosition = position - (directionUp * capsuleBottomTopDistanceToCenter);
Vector3 capsuelTopPosition = position + (directionUp * capsuleBottomTopDistanceToCenter);
if(!Physics.CheckCapsule(capsuelBottomPosition, capsuelTopPosition, radius, mask)) return null;
int overlapSphereCount = Mathf.CeilToInt(((height / radius) - 1));
float overlapShereMoveDistance = (capsuleBottomTopDistanceToCenter * 2) / overlapSphereCount;
Collider[][] colliderArrays = new Collider[overlapSphereCount+1][];
for(int i=0;i<colliderArrays.Length;i++)
{
colliderArrays[i] = Physics.OverlapSphere(capsuelBottomPosition, radius, mask);
capsuelBottomPosition += (directionUp * overlapShereMoveDistance);
}
if(colliderArrays == null) return null;
return CleanUpArrays(colliderArrays);
}
static Collider[] CleanUpArrays(Collider[][] colliderArraysParam)
{
List<int> instanceIdList = new List<int>();
List<Collider> colliderList = new List<Collider>();
for(int i=0;i<colliderArraysParam.Length;i++)
{
for(int j=0;j<colliderArraysParam[i].Length;j++)
{
if(!instanceIdList.Contains(colliderArraysParam[i][j].GetInstanceID()))
{
instanceIdList.Add(colliderArraysParam[i][j].GetInstanceID());
colliderList.Add(colliderArraysParam[i][j]);
}
}
}
return colliderList.ToArray();
}
}