I have written a small code, which is mooving vertices down on mouse click. The problem is in that mesh on change is getting black (only in some places).
Here's the code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MinerScript : MonoBehaviour
{
public MeshFilter filter;
public MeshCollider col;
public GameObject Player;
public float mineSpeed = 200;
Mesh mesh;
Vector3[] vertices;
void Update()
{
filter = transform.parent.GetComponent<PlayerGravity>().mesh;
mesh = filter.GetComponent<MeshFilter>().sharedMesh;
vertices = mesh.vertices;
Ray ray = new Ray(transform.position, transform.forward * 2);
if (Physics.Raycast(ray))
{
if (Input.GetMouseButton(1))
{
int index = Mathf.RoundToInt(ClosestIndexToPoint(ray));
vertices[index] += (-Player.transform.eulerAngles) * Time.deltaTime * mineSpeed;
mesh.vertices = vertices;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
Color[] colors = new Color[mesh.vertices.Length];
colors[index] = Color.red;
mesh.SetColors(colors);
//col.sharedMesh = mesh;
}
}
}
public float ClosestIndexToPoint(Ray ray)
{
if (Physics.Raycast(ray, out RaycastHit hit))
{
Mesh m = hit.transform.GetComponent<MeshFilter>().sharedMesh;
col = hit.transform.GetComponent<MeshCollider>();
int[] tri = new int[3] {
m.triangles[hit.triangleIndex * 3 + 0],
m.triangles[hit.triangleIndex * 3 + 1],
m.triangles[hit.triangleIndex * 3 + 2],
};
float closestDistance = Vector3.Distance(m.vertices[tri[0]], hit.point);
int closestVertexIndex = tri[0];
for (int i = 0; i < tri.Length; i++)
{
float dist = Vector3.Distance(m.vertices[tri[i]], hit.point);
if (dist < closestDistance)
{
closestDistance = dist;
closestVertexIndex = tri[i];
}
}
return closestVertexIndex;
}
else
return -1;
}
I don't think the problem is in color, as i've tried to apply the teture on it.
About code:
It throws a ray, and if it hits any mesh, it is calling func "ClosestIndexToPoint". It returns value of type float. This function gets the triangle a ray hits, and then finds the closest vertecs to it. Then it just mooves it down (or the rotation of our Player object, cause a have a non - flat mesh).
Related
Good afternoon! I'm trying to sew up two meshes. I do this as follows: first I convert the sprite into a mesh, then I duplicate the resulting mesh, shift it along the "z" axis, invert it, and then sew it up. But I faced such a problem: he sews rectangular meshes well, but in circular meshes there are some defects on the sides. So, how can you sew up these sides? (Materials and code)
public class ConvertSpriteInMesh : MonoBehaviour
{
public Sprite sprite;
private MeshDraft meshDraft = new MeshDraft();
private Mesh mesh;
void Start()
{
GetComponent<MeshFilter>().mesh = SpriteToMesh(sprite);
SewingUp();
}
/// <summary>
/// Sewing up nets
/// </summary>
private void SewingUp()
{
mesh = GetComponent<MeshFilter>().mesh;
meshDraft = new MeshDraft(mesh);
int leftVertical = mesh.vertices.Length / 2; // getting the beginning of the left vertical of the mesh
int index = mesh.vertices.Length;
for (int i = 0; i < leftVertical - 1; i++)
{
meshDraft.AddQuad(mesh.vertices[i], mesh.vertices[i+1], mesh.vertices[i + leftVertical + 1],mesh.vertices[i+leftVertical],
index);
index += 4;
}
GetComponent<MeshFilter>().mesh = meshDraft.ToMesh(); // assign the resulting mesh
}
/// <summary>
/// Convert Sprite to Mesh
/// </summary>
/// <param name="_sprite"></param>
/// <returns></returns>
private Mesh SpriteToMesh(Sprite _sprite)
{
// declaring variables
Mesh mesh = new Mesh();
Vector3[] _verticles;
int[] _triangle;
// assigning values
_verticles = Array.ConvertAll(_sprite.vertices, i => (Vector3)i);
_triangle = Array.ConvertAll(_sprite.triangles, i => (int)i);
// changing the size of the array
Array.Resize(ref _verticles, _verticles.Length * 2);
Array.Resize(ref _triangle, _triangle.Length * 2);
// adding another side
for (int i = 0; i < _verticles.Length / 2; i++)
{
_verticles[_verticles.Length / 2 + i] = new Vector3(_verticles[i].x, _verticles[i].y, 0.5f);
}
for (int i = 0; i < _triangle.Length / 2; i++)
{
_triangle[_triangle.Length / 2 + i] = _triangle[i] + (_verticles.Length / 2);
}
// invert the second side
for(int i = _triangle.Length / 2; i < _triangle.Length; i += 3) {
var temp = _triangle[i];
_triangle[i] = _triangle[i + 1];
_triangle[i + 1] = temp;
}
// assigning the mesh
mesh.vertices = _verticles;
mesh.triangles = _triangle;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
return mesh;
}
}
public partial class MeshDraft {
public string name = "";
public List<Vector3> vertices = new List<Vector3>();
public List<int> triangles = new List<int>();
public List<Vector3> normals = new List<Vector3>();
public List<Vector4> tangents = new List<Vector4>();
public List<Vector2> uv = new List<Vector2>();
public List<Vector2> uv2 = new List<Vector2>();
public List<Vector2> uv3 = new List<Vector2>();
public List<Vector2> uv4 = new List<Vector2>();
public List<Color> colors = new List<Color>();
public MeshDraft(Mesh mesh) {
name = mesh.name;
vertices.AddRange(mesh.vertices);
triangles.AddRange(mesh.triangles);
normals.AddRange(mesh.normals);
tangents.AddRange(mesh.tangents);
uv.AddRange(mesh.uv);
uv2.AddRange(mesh.uv2);
uv3.AddRange(mesh.uv3);
uv4.AddRange(mesh.uv4);
colors.AddRange(mesh.colors);
}
public void AddQuad(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, int index, Color color = default(Color)) {
vertices.Add(v0);
vertices.Add(v1);
vertices.Add(v2);
vertices.Add(v3);
Vector3 normal0 = Vector3.Cross(v2 - v1, v3 - v1).normalized;
Vector3 normal1 = Vector3.Cross(v1 - v0, v2 - v0).normalized;
normals.Add(normal0);
normals.Add(normal0);
normals.Add(normal1);
normals.Add(normal1);
colors.Add(color);
colors.Add(color);
colors.Add(color);
colors.Add(color);
triangles.Add(index);
triangles.Add(index + 1);
triangles.Add(index + 2);
triangles.Add(index);
triangles.Add(index + 2);
triangles.Add(index + 3);
}
public Mesh ToMesh() {
var mesh = new Mesh { name = name };
mesh.SetVertices(vertices);
mesh.SetTriangles(triangles, 0);
mesh.SetNormals(normals);
mesh.SetTangents(tangents);
mesh.SetUVs(0, uv);
mesh.SetUVs(1, uv2);
mesh.SetUVs(2, uv3);
mesh.SetUVs(3, uv4);
mesh.SetColors(colors);
return mesh;
}
Successful stitching (screen)
Bad stitching (screen)
I was given an answer on another forum, who is interested, I will leave a link here - https://www.cyberforum.ru/unity/thread2823987.html
I'm the beginner of game coding, and meet some problem...
I would like to make coin stack and then click the coin all the coin would become small and fly to dedicate position, however, the coin position wasn't initialized which causes the Vector3 of coin move up 0.1f every time...
Please help me to solve it!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class createcoin : MonoBehaviour
{ public Transform RightCoinArea;
public Transform LeftCoinArea;
public Sprite sprite1;
List<Vector3> rightcoinpos = new List<Vector3>();
List<Vector3> leftcoinpos = new List<Vector3>();
public Vector3 [] rightpos= new Vector3 [6] ;
public Vector3[] leftpos = new Vector3[6];
// Start is called before the first frame update
void Start()
{
rightcoinpos.Add(rightpos);
leftcoinpos.Add(leftpos);
}
//create coin
public async void coincreate()
{
//coin stack random
for (float i = 0; i <= 0.1f; i += 0.1f)
{
var coin8 = await PoolSystem.Instance.GetGameObject(eBundle.Game, "Flycoin",
rightcoinpos[Random.Range(0, rightcoinpos.Count)] += Vector3.up * i, new Vector3(0.4f, 0.4f, 04f), sFileExtension.Prefab, RightCoinArea);
//to initialize sprite
coin8.GetComponent<SpriteRenderer>().sprite = sprite1;
}
//coin stack random
for (float i = 0; i < 0.2f; i += 0.1f)
{
var coin9 = await PoolSystem.Instance.GetGameObject(eBundle.Game, "Flycoin", leftcoinpos[Random.Range(0, leftcoinpos.Count)] += Vector3.up * i, new Vector3(0.4f, 0.4f, 04f), sFileExtension.Prefab, LeftCoinArea);
//to initialize sprite
coin9.GetComponent<SpriteRenderer>().sprite = sprite1;
}
}
public void Moveout()
{
//gameobject back to the objectpool
if (RightCoinArea.gameObject.transform.localScale == new Vector3(0, 0, 0))
{
PoolSystem.Instance.Recover(RightCoinArea.gameObject);
}
if (LeftCoinArea.gameObject.transform.localScale == new Vector3(0, 0, 0))
{
PoolSystem.Instance.Recover(LeftCoinArea.gameObject);
}
//delete all the position in List
rightcoinpos.Clear();
leftcoinpos.Clear();
//to initialize the position
Vector3 tempos_R = rightpos;
Vector3 tempos_L = leftpos;
rightcoinpos.Add(rightpos);
leftcoinpos.Add(leftpos);
}
public void click()
{
coin_test.GetComponent<SpriteRenderer>().sprite = sprite2_test;
//coin fly to end dedicate pos
DOTween.To(setter: value =>
{
coin_test.position = Parabola(start_test.position, new Vector3(0, 4.5f, 0), 1.5f, value);
}, startValue: 0, endValue: 1, duration: 1.5f)
.SetEase(Ease.Linear);
//change coin scale
transform.DOScale(0.0f, 2.0f).OnComplete(Moveout);
}
//Parabola
public static Vector3 Parabola(Vector3 start, Vector3 end, float height, float t)
{
float Func(float x) => 0.5f * (-height * x * x + height * x);
var mid = Vector3.Lerp(start, end, t);
return new Vector3(mid.x, Func(t) + Mathf.Lerp(start.y, end.y, t), mid.z);
}
}
I'm currently trying to develop an AI for my game that needs to move every minion towards the enemy minions by a specific distance, what I'm currently doing is calculating the distance between all the enemy minions, after that I'll calculate the angle between the current minion and the closest one, and after that I'll apply the formula:
x = minion.x + cos(angle) * distance;
z = minion.z + sin(angle) * distance;
The problem is that the movement seems random, it doesn't always move towards the enemy but instead, it moves randomly
I'll provide the code below
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class EnemyAI : MonoBehaviour {
private float tolerance = 1.2f;
public NavMeshSurface navMesh;
private List<GameObject> board;
private List<Vector3> minionDesiredLocations;
private int currentMinionIndex = 0;
private enum State {
Draw,
Place,
GetBoard,
Move,
MinionMoving
}
private State state = State.Draw;
public GameObject PlaceCard(List<GameObject> hand)
{
//Generate a random integer to see what card to play
int randomIndex = (int) UnityEngine.Random.Range(0, hand.Count - 1);
Debug.Log("AI Generated Index: " + randomIndex);
return hand[randomIndex];
}
private bool MoveMinion(GameObject minion, List<GameObject> enemyMinions)
{
NavMeshAgent minionAgent = minion.GetComponent<NavMeshAgent>();
Card minionCard = minion.transform.Find("Card").GetComponent<Card>();
Vector3 maPosition = minion.transform.position;
//Finding the closest position of the enemy minion
float minDistance = 100.0f;
Vector3 closestMinionPosition = Vector3.negativeInfinity;
foreach (GameObject enemyMinion in enemyMinions)
{
//Calculating distance beetween the enemy AI minion and the enemy
float distance = Vector3.Distance(minion.transform.position, enemyMinion.transform.position);
if (distance <= minDistance)
{
minDistance = distance;
//Attacking the minion is close to the one
if (minDistance <= minionCard.cardRange)
{
float xRange = UnityEngine.Random.Range(-tolerance, tolerance);
float yRange = UnityEngine.Random.Range(-tolerance, tolerance);
closestMinionPosition = enemyMinion.transform.position + new Vector3(xRange, 0, yRange);
minionDesiredLocations[currentMinionIndex] = closestMinionPosition;
minionAgent.SetDestination(closestMinionPosition);
NavMeshHit hit;
if (NavMesh.SamplePosition(closestMinionPosition, out hit, 1.0f, NavMesh.AllAreas))
{
minionDesiredLocations[currentMinionIndex] = hit.position;
minionAgent.SetDestination(hit.position);
return true;
}
}
else
{
//Calculating angle beetween the minion and the target
float angle = GetAngle(minion.transform.position, enemyMinion.transform.position);
float randomDistance = UnityEngine.Random.Range((float)minionCard.cardRange / 2, (float)minionCard.cardRange * 2);
randomDistance = 1.0f;
float x = minion.transform.position.x + (float)Math.Cos(angle) * randomDistance;
float z = minion.transform.position.z + (float)Math.Sin(angle) * randomDistance;
closestMinionPosition = new Vector3(x, 0, z);
NavMeshHit hit;
if (NavMesh.SamplePosition(closestMinionPosition, out hit, 3.0f, NavMesh.AllAreas))
{
minionDesiredLocations[currentMinionIndex] = hit.position;
minionAgent.SetDestination(hit.position);
return true;
}
}
}
}
return false;
}
public bool PerformTurn(GameController gameController)
{
switch (state)
{
case State.Draw:
currentMinionIndex = 0;
gameController.drawCard(1);
state = State.Place;
break;
case State.Place:
//Getting the hand
List<GameObject> hand = gameController.GetHand(1);
//Generate a random integer to see what card to play
int randomIndex = (int)UnityEngine.Random.Range(0, hand.Count - 1);
gameController.PlaceMinion(randomIndex);
state = State.GetBoard;
break;
case State.GetBoard:
board = gameController.GetBoard(1);
minionDesiredLocations = GenerateActualLocations(board);
currentMinionIndex = 0;
state = State.Move;
break;
case State.Move:
//If we have moved all minions
if (currentMinionIndex >= board.Count)
{
Debug.Log("[IA] Passing turn");
state = State.Draw;
gameController.NextPlayer();
return true;
}
else if(MoveMinion(board[currentMinionIndex], gameController.GetBoard(0)))
{
gameController.SetCameraTo(board[currentMinionIndex].transform.position);
MoveMinion(board[currentMinionIndex], gameController.GetBoard(0));
state = State.MinionMoving;
}
break;
case State.MinionMoving:
Vector3 actualMinionPosition = board[currentMinionIndex].transform.position;
Vector3 desiredMinionLocation = minionDesiredLocations[currentMinionIndex];
actualMinionPosition = new Vector3(actualMinionPosition.x, 0, actualMinionPosition.z);
desiredMinionLocation = new Vector3(desiredMinionLocation.x, 0, desiredMinionLocation.z);
if (actualMinionPosition == desiredMinionLocation)
{
Debug.Log("Next Minion");
currentMinionIndex++;
state = State.Move;
}
//Debug lines
if (Input.GetKey(KeyCode.P))
{
Debug.Log("Next Minion");
currentMinionIndex++;
state = State.Move;
}
break;
}
//Continue turn proccessing
return false;
}
private List<Vector3> GenerateActualLocations(List<GameObject> board)
{
List<Vector3> l = new List<Vector3>();
foreach (GameObject minion in board)
{
l.Add(minion.transform.position);
}
return l;
}
private float GetAngle(Vector3 minion, Vector3 target)
{
return Vector3.Angle(minion, target);
}
}
Thanks for the help, I've finally found a solution.
What I've done was calling
agent.SetDestination(enemyMinion.transform.position)
After that I've stored the starting position of the agent, and inside of the logic loop, check the distance between the starting position and the actual position, whenever the distance is greater than the distance that the minion can walk, I'll simply stop the NavMeshAgent
Here's the updated code in case someone needs it
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class EnemyAI : MonoBehaviour {
private float tolerance = 1.2f;
public NavMeshSurface navMesh;
private List<GameObject> board;
private List<Vector3> minionDesiredLocations;
private Vector3 startMinionLocation;
private int currentMinionIndex = 0;
private enum State {
Draw,
Place,
GetBoard,
Move,
MinionMoving
}
private State state = State.Draw;
public GameObject PlaceCard(List<GameObject> hand)
{
//Generate a random integer to see what card to play
int randomIndex = (int) UnityEngine.Random.Range(0, hand.Count - 1);
Debug.Log("AI Generated Index: " + randomIndex);
return hand[randomIndex];
}
private bool MoveMinion(GameObject minion, List<GameObject> enemyMinions)
{
NavMeshAgent minionAgent = minion.GetComponent<NavMeshAgent>();
Card minionCard = minion.transform.Find("Card").GetComponent<Card>();
Vector3 maPosition = minion.transform.position;
//Finding the closest position of the enemy minion
float minDistance = 100.0f;
Vector3 closestMinionPosition = Vector3.negativeInfinity;
foreach (GameObject enemyMinion in enemyMinions)
{
//Calculating distance beetween the enemy AI minion and the enemy
float distance = Vector3.Distance(minion.transform.position, enemyMinion.transform.position);
if (distance <= minDistance)
{
minDistance = distance;
//Attacking the minion is close to the one
float xRange = UnityEngine.Random.Range(-tolerance, tolerance);
float yRange = UnityEngine.Random.Range(-tolerance, tolerance);
closestMinionPosition = enemyMinion.transform.position + new Vector3(xRange, 0, yRange);
minionDesiredLocations[currentMinionIndex] = closestMinionPosition;
minionAgent.SetDestination(closestMinionPosition);
NavMeshHit hit;
if (NavMesh.SamplePosition(closestMinionPosition, out hit, 1.0f, NavMesh.AllAreas))
{
minionDesiredLocations[currentMinionIndex] = hit.position;
minionAgent.isStopped = false;
minionAgent.SetDestination(hit.position);
startMinionLocation = minion.transform.position;
return true;
}
}
}
return false;
}
public bool PerformTurn(GameController gameController)
{
switch (state)
{
case State.Draw:
currentMinionIndex = 0;
gameController.drawCard(1);
state = State.Place;
break;
case State.Place:
//Getting the hand
List<GameObject> hand = gameController.GetHand(1);
//Generate a random integer to see what card to play
int randomIndex = (int)UnityEngine.Random.Range(0, hand.Count - 1);
gameController.PlaceMinion(randomIndex);
state = State.GetBoard;
break;
case State.GetBoard:
board = gameController.GetBoard(1);
minionDesiredLocations = GenerateActualLocations(board);
currentMinionIndex = 0;
state = State.Move;
break;
case State.Move:
//If we have moved all minions
if (currentMinionIndex >= board.Count)
{
Debug.Log("[IA] Passing turn");
state = State.Draw;
gameController.NextPlayer();
return true;
}
else if(MoveMinion(board[currentMinionIndex], gameController.GetBoard(0)))
{
gameController.SetCameraTo(board[currentMinionIndex].transform.position);
MoveMinion(board[currentMinionIndex], gameController.GetBoard(0));
state = State.MinionMoving;
}
break;
case State.MinionMoving:
Vector3 actualMinionPosition = board[currentMinionIndex].transform.position;
float distance = Vector3.Distance(startMinionLocation, actualMinionPosition);
Card card = board[currentMinionIndex].transform.Find("Card").GetComponent<Card>();
NavMeshAgent agent = board[currentMinionIndex].GetComponent<NavMeshAgent>();
if (distance >= card.cardRange)
{
agent.isStopped = true;
currentMinionIndex++;
state = State.Move;
}
//Debug lines
if (Input.GetKey(KeyCode.P))
{
Debug.Log("Next Minion");
currentMinionIndex++;
state = State.Move;
}
break;
}
//Continue turn proccessing
return false;
}
private List<Vector3> GenerateActualLocations(List<GameObject> board)
{
List<Vector3> l = new List<Vector3>();
foreach (GameObject minion in board)
{
l.Add(minion.transform.position);
}
return l;
}
private float GetAngle(Vector3 minion, Vector3 target)
{
return Vector3.Angle(minion, target);
}
}
I created a diagonal line renderer by attaching the following script to an empty game object. How can I extend the line at both ends for a half its length and how can I also extend the line by say 1 unit along the x-axis? Both over a certain period of time.
public class DiagonalLine : MonoBehaviour {
bool firstLineComplete = false;
LineRenderer diagLine;
public Vector3 startPoint = new Vector3 (0, 0, 0);
public Vector3 endPoint = new Vector3 (1.0f, 1.0f, 0);
public float lineDrawSpeed;
// Use this for initialization
void Start () {
diagLine = gameObject.AddComponent<LineRenderer>();
diagLine.material = new Material (Shader.Find ("Sprites/Default"));
diagLine.startColor = diagLine.endColor = Color.green;
diagLine.startWidth = diagLine.endWidth = 0.15f;
diagLine.SetPosition (0, startPoint);
diagLine.SetPosition (1, endPoint);
}
}
This is basic vector math.
You have the line with (from end to start):
Vector3 v = start - end;
and then you extend on each side by half if it:
extensionA = start + (v * 0.5f);
extensionB = end + (v * -0.5f);
If you need to extend by 1 then normalize:
Vector3 v = (start - end).normalized;
extensionA = start + v;
extensionB = end + (v * -1f);
Break your problem into pieces:
1.Extend line by x units on both sides:
This is done with the Ray class. Create a new Ray instance from the startPoint and endPoint variables then use the Ray.GetPoint function to extend the line. You have to do this on both sides to get the new extended lines.
A simple wrapper for the Ray class to simplify this:
Vector3 extendLine(Vector3 startPoint, Vector3 endPoint, ExtendDirection extendDirection, float extendDistance)
{
Ray ray = new Ray();
//Start
if (extendDirection == ExtendDirection.START_POINT)
{
ray.origin = startPoint;
ray.direction = startPoint - endPoint;
}
//End
else if (extendDirection == ExtendDirection.END_POINT)
{
ray.origin = endPoint;
ray.direction = endPoint - startPoint;
}
//Extend
Vector3 newUnityPoint = ray.GetPoint(extendDistance);
//Debug.DrawLine(ray.origin, newUnityPoint, Color.blue);
return newUnityPoint;
}
public enum ExtendDirection
{
START_POINT, END_POINT
}
Extend to the Left end
Vector3 newStartPos = extendLine(startPoint, endPoint, ExtendDirection.START_POINT, 4);
diagLine.SetPosition(0, newStartPos);
Extend to the Right end
Vector3 newEndPos = extendLine(startPoint, endPoint, ExtendDirection.END_POINT, 4);
diagLine.SetPosition(1, newEndPos);
2.For animating/moving it over time, use coroutine and Time.deltaTime. Increment a variable with Time.deltaTime every frame to then use Vector3.Lerp to lerp the from and to value.
See this function for example.
With both combined, below is a complete function to extend both lines over time:
bool isRunning = false;
IEnumerator extentLineOverTime(LineRenderer targetLineRenderer, float extendDistance, float duration)
{
//Calculate Left from extension length
Vector3 fromValLeftPos = targetLineRenderer.GetPosition(0);
//Calculate Right from extension length
Vector3 fromValRightPos = targetLineRenderer.GetPosition(1);
//Calculate Left to extension length
Vector3 newLeftPos = extendLine(fromValLeftPos, fromValRightPos, ExtendDirection.START_POINT, extendDistance);
//Calculate Right to extension length
Vector3 newRightPos = extendLine(fromValLeftPos, fromValRightPos, ExtendDirection.END_POINT, extendDistance);
//Make sure there is only one instance of this function running
if (isRunning)
{
yield break; ///exit if this is still running
}
isRunning = true;
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
//Move to left overtime
Vector3 tempLeftPos = Vector3.Lerp(fromValLeftPos, newLeftPos, counter / duration);
targetLineRenderer.SetPosition(0, tempLeftPos);
//Move to Right overtime
Vector3 tempRightPos = Vector3.Lerp(fromValRightPos, newRightPos, counter / duration);
targetLineRenderer.SetPosition(1, tempRightPos);
yield return null;
}
isRunning = false;
}
USAGE:
LineRenderer diagLine;
public Vector3 startPoint = new Vector3(0, 0, 0);
public Vector3 endPoint = new Vector3(1.0f, 1.0f, 0);
// Use this for initialization
void Start()
{
diagLine = gameObject.AddComponent<LineRenderer>();
diagLine.material = new Material(Shader.Find("Sprites/Default"));
diagLine.startColor = diagLine.endColor = Color.green;
diagLine.startWidth = diagLine.endWidth = 0.15f;
diagLine.SetPosition(0, startPoint);
diagLine.SetPosition(1, endPoint);
//Extend Line Over time
StartCoroutine(extentLineOverTime(diagLine, 4, 3));
}
The StartCoroutine(extentLineOverTime(diagLine, 4, 3)); will extend the line 4 units away from both sides within 3 seconds.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Teleport : MonoBehaviour {
public Vector3 terrainArea;
public float spinSpeed = 2.0f;
public int cloneTeleportations;
public GameObject prefab;
private bool rotate = false;
private bool exited = false;
private Transform[] teleportations;
private Random rnd = new Random();
private void Start()
{
GameObject go = GameObject.Find("Terrain");
Terrain terrain = go.GetComponent(Terrain);
terrainArea = terrain.terrainData.size;
for (int i = 0; i < cloneTeleportations; i++)
{
GameObject Teleportaion = Instantiate(prefab, new Vector3(Random.Range(i * 10.0F, i * 50.0F), 0, Random.Range(i * 10.0F, i * 50.0F)), Quaternion.identity);
Teleportaion.transform.parent = this.transform;
Teleportaion.transform.tag = "Teleportation";
}
}
}
Now some gameobjects are out of the terrain area.
What I want to do is to keep the clones to be in random position but only inside the terrain area.
How I do Instantiate Objects inside the terrain area?
I noticed that you are creating new instance of the Random class. Don't do that with Unity's Random API. Just use Random.Range to generate random numbers.
As for generating random GameObjects on a terrain:
1.Find the X position:
Min = terrain.terrainData.size.x.
Max = terrain.transform.position.x + terrain.terrainData.size.x.
The final random X should be:
randX = UnityEngine.Random.Range(Min, Min + Max);
2.Find the Z position:
Min = terrain.transform.position.z;
Max = terrain.transform.position.z + terrain.terrainData.size.z;
The final random Z should be:
randZ = UnityEngine.Random.Range(Min, Min + Max);
3.Find the Y position:
The y-axis does not have to be random. Although, you can make it a random value if you want.
It just has to be over the terrain so that the Instantiated Object will not be under the terrain.
This is where Terrain.SampleHeight comes into place. You must use this function in order to perfectly generate a position that is not under the terrain. You need the result from #1 and #2 to use this:
yVal = Terrain.activeTerrain.SampleHeight(new Vector3(randX, 0, randZ));
If you want to apply offset to the y-axis, you can now do it at this time.
yVal = yVal + yOffset;
Below is a general example. You have to use this example to extend your current code.
public GameObject prefab;
public Terrain terrain;
public float yOffset = 0.5f;
private float terrainWidth;
private float terrainLength;
private float xTerrainPos;
private float zTerrainPos;
void Start()
{
//Get terrain size
terrainWidth = terrain.terrainData.size.x;
terrainLength = terrain.terrainData.size.z;
//Get terrain position
xTerrainPos = terrain.transform.position.x;
zTerrainPos = terrain.transform.position.z;
generateObjectOnTerrain();
}
void generateObjectOnTerrain()
{
//Generate random x,z,y position on the terrain
float randX = UnityEngine.Random.Range(xTerrainPos, xTerrainPos + terrainWidth);
float randZ = UnityEngine.Random.Range(zTerrainPos, zTerrainPos + terrainLength);
float yVal = Terrain.activeTerrain.SampleHeight(new Vector3(randX, 0, randZ));
//Apply Offset if needed
yVal = yVal + yOffset;
//Generate the Prefab on the generated position
GameObject objInstance = (GameObject)Instantiate(prefab, new Vector3(randX, yVal, randZ), Quaternion.identity);
}