Я создал сетку для препятствий на сетке от x -6 до x 6. Объекты перемещаются по оси -z к игроку.
Они движутся не только по оси x, но и по z. По какой-то причине, несмотря на то, что закодировал спавнер, который помещает объект каждые 2 значения, он помещает их на долю от каждого. И получает меньше каждый ряд. Таким образом, объект, помещенный в x2, следующий ряд в x2 будет в x1.999987 и затем в x1.998 и т. Д.
Значение x каждого объекта должно быть только одним из следующих (-6, -4 , -2, 0, 2, 4, 6)
Это вызывает у меня проблему, потому что мне нужно также иметь возможность выбрать два объекта и поменять их местами. Это требует, чтобы мой скрипт сканировал доску на предмет активных объектов, находил значения x объектов и менял местами. Если значения x не являются solid целыми числами, другие объекты не будут обнаружены.
Заранее благодарим вас за любые советы:)
![enter image description here](https://i.stack.imgur.com/iiIu5.jpg)
Код вызова:
void SpawnGrid()
{
for (int x = 0; x < gridX; x++)
{
for (int z = 0; z < gridZ; z++)
{
float x1 = Mathf.Round(x * gridSpacingOffset);
float z1 = Mathf.Round(z * gridSpacingOffset);
Debug.Log("x1: " + x1);
Debug.Log("x2: " + z1);
Vector3 spawnPosition = new Vector3(x1, 0, z1) + gridOrigin;
PickAndSpawn(spawnPosition, Quaternion.identity);
}
}
}
void PickAndSpawn(Vector3 positionToSpawn, Quaternion rotationToSpawn)
{
// Pick a "random" number between 0 and the length of the obstacle array
int randomIndex = Random.Range(0, itemsToPickFrom.Length);
Debug.Log("RandomIndex is: " + randomIndex);
// Declare obstacle types
obj = ObjectPooler.SharedInstance.GetPooledObject("Obstacle_Type_1");
obj1 = ObjectPooler.SharedInstance.GetPooledObject("Obstacle_Type_2");
obj2 = ObjectPooler.SharedInstance.GetPooledObject("Obstacle_Type_3");
obj3 = ObjectPooler.SharedInstance.GetPooledObject("Obstacle_Type_4");
// Add obstacles to an array
objectTypes[0] = obj;
objectTypes[1] = obj1;
objectTypes[2] = obj2;
objectTypes[3] = obj3;
// Spawn the obstacle chosen by the random index number
if (objectTypes[randomIndex] == null)
return;
objectTypes[randomIndex].transform.position = positionToSpawn;
objectTypes[randomIndex].transform.rotation = rotationToSpawn;
ontheBoard.Add(objectTypes[randomIndex]);
objectTypes[randomIndex].SetActive(true);
}
Код движения объекта:
void Start () {
currentPos = transform.position;
}
void Update()
{
destinationPos = currentPos;
destinationPos.z = destinationPos.z - moveStep;
currentPos = transform.position;
}
void FixedUpdate()
{
transform.position = Vector3.MoveTowards(transform.position, destinationPos, moveSpeed * Time.fixedDeltaTime);
}
Код обмена:
private void swapIt(Vector3 pos1, Vector3 pos2)
{
if (swap != true)
{
startPos = pos1;
endPos = pos2;
archMidPos = startPos + (endPos - startPos) / 2 + Vector3.up * archHeight;
swap = true;
}
}
void Update()
{
moveSpeed = obj1.GetComponent<Cube_Control>().moveSpeed;
moveStep = obj1.GetComponent<Cube_Control>().moveStep;
destinationPosObj1 = currentPosObj1;
destinationPosObj1.z = destinationPosObj1.z - moveStep;
currentPosObj1 = obj1.transform.position;
destinationPosObj2 = currentPosObj2;
destinationPosObj2.z = destinationPosObj2.z - moveStep;
currentPosObj2 = obj2.transform.position;
// For testing press SPACEBAR to swap objects
if (Input.GetKeyDown(KeyCode.Space))
{
/*
int randomIndex = Random.Range(0, lvlManager.GetComponent<Grid_Spawn>().ontheBoard.Count);
obj1 = lvlManager.GetComponent<Grid_Spawn>().ontheBoard[randomIndex];
foreach (GameObject ob in lvlManager.GetComponent<Grid_Spawn>().ontheBoard)
{
if (ob.transform.position.x == (obj1.transform.position.x + 4))
{
obj2 = ob;
swapIt(obj1.transform.position, obj2.transform.position);
}
else { Debug.Log("No object nearby to swap"); }
}*/
swapIt(obj1.transform.position, obj2.transform.position);
}
}
private void FixedUpdate()
{
//loat cnt = gs.ontheBoard.Count;
//Debug.Log("ontheboard count: " + cnt);
if (swap == true)
{
if (count < 1.0f)
{
count += 1.0f * Time.fixedDeltaTime;
// Lerp the primary object to the new position in an arching motion
Vector3 archMidPosObj1 = archMidPos;
Vector3 endPosObj1 = endPos;
archMidPosObj1.z = archMidPosObj1.z - moveStep;
endPosObj1.z = endPosObj1.z - moveStep;
Vector3 m1 = Vector3.Lerp(startPos, archMidPosObj1, count);
Vector3 m2 = Vector3.Lerp(archMidPosObj1, endPosObj1, count);
// Move Object 1
obj1.transform.position = Vector3.Lerp(m1, m2, count);
// Calculate the inverse arch (-Y) and Lerp the secondary object in a negative arching motion
float midposY = archMidPos.y - (archMidPos.y * 2);
Vector3 archMidPosReverse = archMidPos;
archMidPosReverse.y = midposY;
Vector3 obj2StartPos = startPos;
archMidPosReverse.z = archMidPosReverse.z - moveStep;
obj2StartPos.z = obj2StartPos.z - moveStep;
Vector3 m3 = Vector3.Lerp(endPos, archMidPosReverse, count);
Vector3 m4 = Vector3.Lerp(archMidPosReverse, obj2StartPos, count);
// Move Object 2
obj2.transform.position = Vector3.Lerp(m3, m4, count);
// Reset swap boolean and count once object has swapped places
if (obj1.transform.position.x == endPos.x)
{
swap = false;
count = 0;
}
}
}
}
}
РЕДАКТИРОВАТЬ 04/04/2020:
Хорошо, поэтому я заметил, что значение x смещается из-за умножения на fixedDeltaTime в FixedUpdate ()
Если вы присоедините приведенный ниже скрипт к объекту на x круглый номер и нажмите кнопку воспроизведения, он будет двигаться вдоль оси z, x сместится с круглого числа на длинное десятичное с плавающей запятой.
Если вы закомментируете строку в FixedUpdate (transform.position = Vector3.MoveTowards (transform .position, destinationPos, moveStep * Time.fixedDeltaTime);) и удалите косые черты из оператора ниже, теперь объект остается на всем числе x, однако скорость вдоль оси z больше не является постоянной и теряет синхронизацию c каждый кадр с другим объекты на одной оси Z, движущиеся в то же pace ..
Настройки, которыми я сейчас пользуюсь:
- moveSpeed: 4
- moveStep: 2.5
- Mass: 1
- Drag / Angular Drag: Нет
- Использовать гравитацию: Нет
- isKinemati c: Да
- Интерполировать: Нет
- Столкновение: непрерывный спекулятивный
- Ограничения: отсутствуют
код:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cube_Control : MonoBehaviour
{
public float moveSpeed;
public float moveStep;
public Vector3 currentPos;
public Vector3 destinationPos;
private Rigidbody rb;
// Start is called before the first frame update
void Start()
{
currentPos = transform.position;
currentPos.x = Mathf.Round(currentPos.x);
rb = this.GetComponent<Rigidbody>();
}
void Update()
{
destinationPos = currentPos;
destinationPos.z = destinationPos.z - moveStep;
destinationPos.x = Mathf.Round(destinationPos.x);
currentPos = transform.position;
currentPos.x = Mathf.Round(currentPos.x);
}
// Update is called once per frame
void FixedUpdate()
{
transform.position = Vector3.MoveTowards(transform.position, destinationPos, moveStep * Time.fixedDeltaTime);
//transform.position = Vector3.MoveTowards(transform.position, destinationPos, moveStep);
}
public void setObstacleSpeed(float speed)
{
moveSpeed = speed;
}
public void setObstacleMoveStep(float step)
{
moveStep = step;
}
private void Destroy(GameObject obj)
{
obj.SetActive(false);
}
private void OnTriggerEnter(Collider other)
{
Debug.Log("Ow! I Feel Triggerd " + other);
if (other.gameObject.tag == "WallOfDoom")
{
Debug.Log("I hit the WALL OF DOOOOOOMMM!");
Destroy(this.gameObject);
}
else if (other.gameObject.tag == "Plyr_Bullet")
{
Destroy(this.gameObject);
}
}
private void OnCollisionEnter(Collision collision)
{
Debug.Log("Ow! I Feel Triggerd " + collision);
if (collision.gameObject.tag == "WallOfDoom")
{
Debug.Log("I hit the WALL OF DOOOOOOMMM!");
Destroy(this.gameObject);
}
}
}