Как мне улучшить и оптимизировать мой скрипт движения моделей? В модуле движения у меня есть путевые точки, которые я задаю когда начинаю делать сцену: Сам скрипт splineMove получился громоздким. У меня сцены разбиты на 4 типа:
1 Distribution.Когда есть в начале путевые точки(M-113 (0)cloneMiniPath), общие путевые точки(GroupPath) и конечные путевые точки(M-113 (0)_ENDcloneMiniPath).
2 Shooting. Когда модели не двигаются, а просто стоят на сцене и ведут стрельбу.
3 ShellingMovement. Когда их обстре́ливают во время движения.
4 DistributionOne. Когда есть один общий путь(замкнуты или не замкнуты) в конце которого движение начинается в начале первой путевой точке.
Массив путевых точек - public PathManager pathContainer;
Текущая путевая точка, на данный момент времени - public int currentPoint;
Объект в группе относительно, которого считается скорость движения позади идущей техники public GameObject LeaderGObjInstance = null;
.
if (this.LeaderGObjInstance != null && this.LeaderGObjInstance.gameObject.name != transform.name)
{
float DistanceObj = Vector3.Distance(transform.position, GameObject.Find(this.LeaderGObjInstance.gameObject.name).transform.position);
System.Random r = new System.Random();
var space = r.Next(25, 30);
//if(SceneName == "DistributionThree"){space = r.Next (40, 50);}else{space = r.Next (25, 30);}
if (DistanceObj > (float)space)
{
speed = speed + 0.1f;
if (speed > 6)
{
speed = 6;
}
}
else if (DistanceObj <= (float)space)
{
speed = speed - 0.3f;
if (speed <= 0)
{
speed = 0;
}
}
}
Инициализация, Start, Update:
...
public class splineMove : MonoBehaviour
{
// Массив путевых точек
public PathManager pathContainer;
public Vector3 offset;
public bool onStart = true;
public float speed = 5f;
// Текущая путевая точка, на данный момент времени
[HideInInspector]
public int currentPoint = 0;
[HideInInspector]
public float force = 5;
[HideInInspector]
public Rigidbody rb = null;
[HideInInspector]
public float dis_changewaypoint = 5F;
private Vector3 current_waypoint;
[HideInInspector]
public float turn_speed = 1F;
[SerializeField]
public float ddelta = 0.0f;
GameObject GOSelect = null;
// Объект в группе относительно, которого считается скорость движения позади идущей техники
[SerializeField]
public GameObject LeaderGObjInstance = null;
public bool stopModelBool = false;
public bool DistributionBool = false;
// float time = 0;
int indexDamegedModel = 1;
bool boolDetour = false;
bool boolDetourLeftRight = false;
List<Vector3> tempDetourTrapeze = new List<Vector3>();
int tempCountDetourTrapeze = 0;
GameObject GamObjList = null;
GameObject CameraGamObj = null;
RTCTankController tankController = null;
RTCTankGunController gunController = null;
string SceneName;
public enum SceneType
{
Distribution,
Shooting,
ShellingMovement,
DistributionOne
}
public SceneType sceneType = SceneType.Distribution;
public int startTimeInterval = 10;
public Vector3 targetDefeat;
public GameObject targetRotationCameraGameObj;
[Header("Sensors")]
public float sensorLength = 20f;
public Vector3 frontSensorPosition = new Vector3(0f, 3f, 0f);
public float frontSideSensorPossition = 2f;
public float frontSensorAngle = 30f;
int ExplCount = 0;
void Awake()
{
if (transform.name != "Vehicles")
{
initFindAllObj();
if (sceneType == SceneType.Distribution)
{
onStart = false;
stopModelBool = false;
SavingGroupOFObjectsManager SGObjManager = GamObjList.GetComponent<SavingGroupOFObjectsManager>() as SavingGroupOFObjectsManager;
GameObject[] LOrder = SGObjManager.ListOrder;
for (int i = 0; i < LOrder.Length; i++)
{
if (LOrder[i].name == transform.name)
{
Invoke("BoolOnStart", (float)i * startTimeInterval);
// BoolOnStart();
break;
}
}
Leader.LeaderGObj = new GameObject();
Leader.index = 0;
Leader.LeaderGObj.name = "empty";
}
else if (sceneType == SceneType.ShellingMovement)
{
if (sceneType == SceneType.ShellingMovement)
{
if (transform.name == "Camera")
{
Invoke("doWorkInvokeTwo", 56f);
Invoke("DefeatList", 54f);
Invoke("doWorkInvokeTwoCancel", 90f);
}
}
else if (SceneName == "ShellingMovementTwo")
{
doWorkInvokeTwo();
Invoke("Defeat", 10f);
}
else if (SceneName == "ShellingMovementThree")
{
doWorkInvokeTwo();
Invoke("Defeat", 5f);
Invoke("Defeat", 40f);
Invoke("Defeat", 55f);
}
Leader.LeaderGObj = new GameObject();
Leader.index = 0;
Leader.LeaderGObj.name = "empty";
}
else if (sceneType == SceneType.Shooting)
{
if (transform.name != "Camera")
{
onStart = false;
}
}
currentPoint = 0;
if (pathContainer)
{
transform.position = pathContainer.waypoints[currentPoint].position;
current_waypoint = pathContainer.waypoints[currentPoint].position;
Vector3 relativePos = current_waypoint - transform.position;
Face_waypoint(relativePos);
}
}
ExplCount = 0;
}
void initFindAllObj()
{
if (transform.name != "Camera")
{
Transform Gun;
if (Gun = transform.Find("MainGunGroup"))
{
gunController = Gun.GetComponentInChildren<RTCTankGunController>();
}
}
GamObjList = GameObject.Find("Vehicles");
CameraGamObj = GameObject.Find("Camera");
SceneName = SceneManager.GetActiveScene().name;
tankController = transform.GetComponent<RTCTankController>();
rb = GetComponent<Rigidbody>();
}
void BoolOnStart()
{
if (transform.name != "Vehicles")
{
onStart = true;
// onStart = (onStart==true) ? false : true;
}
// if(SceneName=="ShellingMovement") {
// CameraGamObj.GetComponent<RTCCamera> ().enabled = true;
// GOSelect = null;
// }
}
void Update()
{
if (transform.name != "Vehicles")
{
if (onStart)
{
EnemyMovement();
}
if (sceneType == SceneType.ShellingMovement)
{
CameraActivation();
if (gunController != null) { gunController.toOriginalRotationGun(); }
}
else if (sceneType == SceneType.Shooting)
{
ShootingTarget(targetDefeat);
if (SceneName == "ShootingDefeat")
{
//if(transform.name=="Camera") {
CameraActivation();
//}
}
}
else
{
if (gunController != null) { gunController.toOriginalRotationGun(); }
}
}
}
Сам код движения моделей по путевым точкам:
void EnemyMovement()
{
if (pathContainer != null)
{
if (transform.name != "Camera")
{
if (this.LeaderGObjInstance != null && this.LeaderGObjInstance.gameObject.name != transform.name)
{
float DistanceObj = Vector3.Distance(transform.position, GameObject.Find(this.LeaderGObjInstance.gameObject.name).transform.position);
System.Random r = new System.Random();
var space = r.Next(25, 30);
//if(SceneName == "DistributionThree"){space = r.Next (40, 50);}else{space = r.Next (25, 30);}
if (DistanceObj > (float)space)
{
speed = speed + 0.1f;
if (speed > 6)
{
speed = 6;
}
}
else if (DistanceObj <= (float)space)
{
speed = speed - 0.3f;
if (speed <= 0)
{
speed = 0;
}
}
}
if (tankController)
{
tankController.Inputs((float)speed * 1 / 30);
}
}
float range = speed * Time.deltaTime;
Vector3 relativePos = current_waypoint - transform.position;
Waypoint_selecetion_code(relativePos);
current_waypoint = pathContainer.waypoints[currentPoint].position;
if (sceneType == SceneType.DistributionOne)
{
RotationCamera();
//transform.position = Vector3.MoveTowards(transform.position, pathContainer.waypoints[currentPoint].position, range - ddelta);
}
else if (sceneType == SceneType.ShellingMovement)
{
if (transform.name == "Camera")
{
transform.LookAt(LeaderGObjInstance.transform);
}
else
{
Face_waypoint(relativePos);
}
}
else
{
Face_waypoint(relativePos);
// transform.position = Vector3.MoveTowards(transform.position, pathContainer.waypoints[currentPoint].position, range - ddelta);
// Moveobject();
}
transform.position = Vector3.MoveTowards(transform.position, pathContainer.waypoints[currentPoint].position, range - ddelta);
Moveobject();
}
}
Метод выбора следующей путевой точки и метод старта, остановки движения:
void Waypoint_selecetion_code(Vector3 relativePos)
{
if (Mathf.Abs(relativePos.x) < dis_changewaypoint && Mathf.Abs(relativePos.z) < dis_changewaypoint)
{
currentPoint++;
if (currentPoint < pathContainer.waypoints.Length)//waypoints.Count shows number of elements in list
{
current_waypoint = pathContainer.waypoints[currentPoint].position;
}
else
{
if (sceneType == SceneType.Shooting && transform.name == "Camera")
{
onStart = true;
currentPoint = 0;
current_waypoint = pathContainer.waypoints[currentPoint].position;
}
else if (sceneType == SceneType.Distribution && DistributionBool == false)
{
SavingGroupOFObjectsManager ParentGamObj = transform.gameObject.GetComponentInParent<SavingGroupOFObjectsManager>();
transform.gameObject.GetComponent<splineMove>().pathContainer = ParentGamObj.pathCont;
if (transform.name != "Camera")
{
if (Leader.LeaderGObj.name == "empty")
{
Leader.LeaderGObj = transform.gameObject;
this.LeaderGObjInstance = Leader.LeaderGObj;
}
else
{
this.LeaderGObjInstance = Leader.LeaderGObj;
Leader.LeaderGObj = transform.gameObject;
}
}
DistributionBool = true;
currentPoint = 0;
current_waypoint = pathContainer.waypoints[currentPoint].position;
onStart = true;
}
else if (sceneType == SceneType.Distribution)
{
if (stopModelBool)
{
currentPoint = pathContainer.waypoints.Length - 1;
Invoke("BoolOnStartfalse", 1f);
}
else
{
stopModelBool = true;
PathSelect();
current_waypoint = pathContainer.waypoints[currentPoint].position;
onStart = true;
this.LeaderGObjInstance = null;
}
}
else if (sceneType == SceneType.ShellingMovement)
{
currentPoint--;
onStart = false;
//speed = 0f;
}
else
{
currentPoint = 0;
current_waypoint = pathContainer.waypoints[currentPoint].position;
onStart = true;
}
}
}
}
void BoolOnStartfalse()
{
onStart = false;
speed = 0f;
// GetComponent<Rigidbody> ().useGravity = false;
}
public void PathSelect()
{
PathManager[] AllPath = GameObject.Find("AllPathManager").GetComponentsInChildren<PathManager>();
//Regex PathRegex = new Regex(@""+transform.gameObject.name+"");
for (int i = 0; i < AllPath.Length; i++)
{
string pattern = AllPath[i].name;
if (pattern.Contains(transform.gameObject.name + "_END"))
{
transform.gameObject.GetComponent<splineMove>().pathContainer = AllPath[i];
currentPoint = 0;
}
}
}
Метод поворота в сторону движения и физика:
void Moveobject()
{
if (rb != null)
{
if (Mathf.Abs(force) > Mathf.Abs(rb.velocity.z + rb.velocity.x))
{
rb.AddForce(transform.forward * force);
}
}
}
void Face_waypoint(Vector3 relativePos)
{
Quaternion rotation = Quaternion.LookRotation(relativePos, Vector3.up);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * turn_speed); // slerp ( from.rotation, to.rotation, speed)
}
В группе сейчас 17 объектов, но может быть и до 200 объектов. Я вешаю на каждую модель этот скрипт , а так же на камеру.
Из того, что лежит совсем на поверхности:
GameObject.Find()
. Мало того, что это дурной стиль в Unity, дак еще и дорогостоящая операция. Лучше делать ссылки в инспекторе напрямую. Это быстрее и эффективней.GetComponent()
. Тоже самое, что и в предыдущем пункте.Update()
, я бы задумался о том, что это не лучшее решение. Например, вы можете задавать тип объекта (враг, друг, камера или еще какие типы) заведя для этих целей специальный Enum и поле у самого объекта, которое вы будете устанавливать в инспекторе. Такое сравнение в коде будет эквивалентом сравнения 2 int значений, которые вам не придется ни откуда получать (так как установите их в инспекторе). Кроме того, вы еще и избавитесь от постоянных вызовов transform.name. А это тоже небольшой бонус, учитывая, что вы будете использовать закэшированные значения.Update()
за один кадр. Магические методы в юнити достаточно дорогие. Оптимизировать это достаточно легко - создайте отдельный класс-менеджер, который будет иметь ссылки на всех юнитов. Удалите метод Update() из кода самих юнитов и перенесите содержимое этого метода в какой-либо свой публичный метод. В самом классе-менеджере объявите метод Update()
(который теперь будет 1 на всех) и в теле этого метода вызывайте напрямую новый публичный метод для перемещения юнитов.Достаточно мелочь, но при большом количестве объектов актуально:
System.Random r = new System.Random();
var space = r.Next(25, 30);
Объект типа System.Random()
можно создать только 1 раз, например при инициализации объекта, либо напрямую в свойстве или конструкторе. А каждый раз, когда надо получить новое число, просто вызывать r.Next(25, 30);
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Всем привет! У меня есть первый массив gameobject'ов (firstArr), где изначально лежат gameobject'ы с тегом Point и именами Point n (где n от 1 до 9)Мне нужно, чтобы...
Я пытаюсь подключиться к базе данных, используя Entity Framework, но получаю такую ошибку: