I've been trying to create a road mechanic but when I instantiate a mesh, it fails to even create.
I have a version where it's a mesh created in the script(commented) and it works as intended, but when i switch to the instantiated, the roadStart ray and roadend ray both work. I followed a tutorial by quill18 to get a sense of where to go. But I got to a point where I got so frustrated I just copy and pasted and it still failed to work.
bool ClickLoc(out Vector3 point)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
print(ray);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
point = hit.point;
return true;
}
point = Vector3.zero;
return false;
}
void CreateRoad(Vector3 roadStart, Vector3 roadEnd)
{
float width = 1;
float length = Vector3.Distance(roadStart, roadEnd);
if (length < .5)
{
return;
}
GameObject road = (GameObject)Instantiate(prefabRoad);
// GameObject road = new GameObject ("road", typeof(MeshRenderer),typeof(MeshFilter));
road.transform.position = roadStart + new Vector3(0, 0.01f, 0);
road.transform.rotation = Quaternion.FromToRotation(Vector3.right, roadEnd - roadStart);
Debug.Log(road.transform.rotation.eulerAngles);
Vector3[] vertices = {
new Vector3(0, 0, -width/2),
new Vector3(1, 0, -width/2),
new Vector3(1, 0, width/2),
new Vector3(0, 0, width/2)
};
int[] triangles = {
1, 0, 2, // triangle 1
2, 0, 3 // triangle 2
};
Vector2[] uv = {
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(1, 1),
new Vector2(0, 1)
};
Vector3[] normals = {
Vector3.up,
Vector3.up,
Vector3.up,
Vector3.up
};
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uv;
mesh.normals = normals;
MeshFilter mesh_filter = road.GetComponent<MeshFilter>();
MeshRenderer mr = road.GetComponent<MeshRenderer>();
mesh_filter.mesh = mesh;
}
Vector3 roadStart;
Vector3 roadEnd;
void Update()
{
if (yes == true & Input.GetMouseButtonDown(0) )
{
ClickLoc(out roadStart);
}
if (Input.GetMouseButtonUp(0))
{
ClickLoc(out roadEnd);
print(click);
if (roadStart.magnitude != 0)
{
CreateRoad(roadStart, roadEnd);
}
// if (click == false)
// {
// CreateRoad(roadStart, roadEnd);
// mid = true;
//}
}
if (Input.GetMouseButtonUp(1))
{
click = false;
}
}
}
The road created will start at the center of the map and end at my mouse position
I tried and copy your CreateRoad() method and took a quad, cleared the mesh from meshfilter and used that as the roadPRefab and it works. Think it might be as derHugo says; that some portion of your code does not get called.
Related
I have such a problem, maybe someone will help. I am making a game and I need to make a dice that goes in the direction opposite to the click. For example, clicking on the back of a cube moves it forward, etc. Gravity must act on the cube as shown in the figure below. Unfortunately, the cube does not change height, but only the position of X and Z. Please help.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCube : MonoBehaviour
{
Vector3 movePosition;
public float time = 0.02f;
[HideInInspector]
public bool blockClick = false;
private void Start()
{
movePosition = transform.position;
}
private void Update()
{
blockClick = false;
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit raycastHit;
if (Physics.Raycast(ray, out raycastHit))
{
string hitName = raycastHit.transform.name;
if (hitName == "MoveCube")
{
move(raycastHit);
blockClick = true;
}
}
}
transform.position = Vector3.Lerp(
transform.position,
movePosition,
time);
}
public void move(RaycastHit raycastHit)
{
Vector3 incomingVec = raycastHit.normal - Vector3.up;
// South
if (incomingVec == new Vector3(0, -1, -1))
{
movePosition = movePosition + new Vector3(0, 0, 1);
return;
}
// North
if (incomingVec == new Vector3(0, -1, 1))
{
movePosition = movePosition + new Vector3(0, 0, -1);
return;
}
// West
if (incomingVec == new Vector3(-1, -1, 0))
{
movePosition = movePosition + new Vector3(1, 0, 0);
return;
}
// East
if (incomingVec == new Vector3(1, -1, 0))
{
movePosition = movePosition + new Vector3(-1, 0, 0);
return;
}
}
}
From what I know, changing the transform.position of a gameObject with a rigidbody will mess with Unity's physics, and it won't work as intended. I suggest trying to apply a force from the position of the mouse's click instead of moving the cube's position manually (if this makes sense to do for your purposes). Here is the documentation for Rigidbody.AddForce
im making a gravity thing so when you right click it should make the character and camera rotate but im not really sure how to make the camera rotate. this is the code i have for the gravity.
if (Input.GetMouseButtonDown(1) && grounded)
{
Physics.gravity = new Vector3(0, 10.0f, 0);
}
if (Input.GetMouseButtonDown(0) && grounded)
{
Physics.gravity = new Vector3(0, -10.0f, 0);
}
public Transform cam;
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(1) && grounded)
{
Physics.gravity = new Vector3(0, 10.0f, 0);
cam.rotation = Quaternion.Euler(0f, 0f, 180f);
}
if (Input.GetMouseButtonDown(0) && grounded)
{
Physics.gravity = new Vector3(0, -10.0f, 0);
cam.rotation = Quaternion.Euler(0f, 0f, 0f);
}
}
It's drawing a triangle but also give exception.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshGenerator : MonoBehaviour
{
public GameObject meshPrefab;
public Vector3[] newVertices;
public Vector2[] newUV;
public int[] newTriangles;
private Mesh mesh;
void Start()
{
Mesh meshprefab = meshPrefab.GetComponent<MeshFilter>().sharedMesh;
newVertices = meshprefab.vertices;
newUV = meshprefab.uv;
newTriangles = meshprefab.triangles;
mesh = new Mesh();
mesh = gameObject.GetComponent<MeshFilter>().mesh;
mesh.Clear();
mesh.uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 0.25f), new Vector2(0.25f, 0.25f) };
mesh.vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 0.25f, 0), new Vector3(0.25f, 0.25f, 0) };
mesh.triangles = new int[] { 0, 1, 2 };
}
}
The exception is on the line:
mesh.uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 0.25f), new Vector2(0.25f, 0.25f) };
Mesh.uv is out of bounds. The supplied array needs to be the same size as the Mesh.vertices array.
UnityEngine.Mesh:set_uv(Vector2[])
You need to move the vertex array assignment statement to before the uv one, because Unity currently thinks that the number of vertices is zero.
mesh.vertices = ...
mesh.uv = ...
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.
I have make a triangle through my code. see below:
void TriangleMaker()
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//vertices
const int verticeCount = 3;//how many vertices for triangle its 3
Vector3[] vertices = new Vector3[verticeCount]{
//bottom left.orgin of the gameobject,
new Vector3(0,0,0),
new Vector3(width,0,0),
new Vector3(width, height,0)
};
//triangles
int[] tri = new int[6];
tri[0] = 0; //go clock wise always to make triangle from your vertices
tri[1] = 1;
tri[2] = 2;
//normals
//show the direction of objects
Vector3[] normals = new Vector3[3];
normals[0] = -Vector3.up;
normals[1] = -Vector3.up;
normals[2] = -Vector3.up;
mesh.vertices = vertices;
mesh.triangles = tri;
mesh.normals = normals;
}
The script is attached to child game-object of my camera and its showing the triangle but i want to map exactly my triangle to Camera’s view angle.
Also tried GeometryUtility.CalculateFrustumPlanes as Niki answer suggested and the result is not according to expectation:
2: https://docs.unity3d.com/ScriptReference/GeometryUtility.CalculateFrustumPlanes.html
Well I just found it in Unity docs:
https://docs.unity3d.com/ScriptReference/GeometryUtility.CalculateFrustumPlanes.html
P.S: I was so surprised to find this in docs. I think you are the only person in the world who needs this, finally. :D
EDIT:
Ok I edited your script. This visualizes camera's upper frustum plane. Note that this works in global space so move the camera at (0 0 0) position and (0 0 0) rotation to see the result. But I guess you can add the rest of the planes and turn this into local space yourself.
using UnityEngine;
using System.Collections;
public class FrustumScript : MonoBehaviour {
private void Start()
{
TriangleMaker();
}
void TriangleMaker()
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
Camera cam = Camera.main;
//vertices
Vector3[] vertices = new Vector3[3]
{
new Vector3(0, 0, 0),
cam.ViewportToWorldPoint(new Vector3(0, 1, cam.farClipPlane)),
cam.ViewportToWorldPoint(new Vector3(1, 1, cam.farClipPlane))
};
//triangles
int[] tri = new int[6];
tri[0] = 0; //go clock wise always to make triangle from your vertices
tri[1] = 1;
tri[2] = 2;
//normals
//show the direction of objects
Vector3[] normals = new Vector3[3];
normals[0] = -Vector3.up;
normals[1] = -Vector3.up;
normals[2] = -Vector3.up;
mesh.vertices = vertices;
mesh.triangles = tri;
mesh.normals = normals;
}
}