The name `Math' does not exist in the current context - c#

I have the Code below and I'm trying to round the PerlinNoise(x,z) so I've put it equal to Yscale and tried to round it. the issue is that I get the error "The name `Math' does not exist in the current context" for that Line. Any Ideas?
using UnityEngine;
using System.Collections;
public class voxelcreate : MonoBehaviour {
private int origin = 0;
private Vector3 ChunkSize = new Vector3 (32,6,32);
private float Height = 10.0f;
private float NoiseSize = 10.0f;
private float Yscale=0;
private GameObject root;
public float PerlinNoise(float x, float y)
{
float noise = Mathf.PerlinNoise( x / NoiseSize, y / NoiseSize );
return noise * Height;
}
// Use this for initialization
void Start () {
for(int x = 0; x < 33; x++){
bool isMultiple = x % ChunkSize.x == 0;
if(isMultiple == true){
origin = x;
Chunk();}
}
}
// Update is called once per frame
void Chunk (){
int ranNumber = Random.Range(8, 80);
int ranNumber2 = Random.Range(8, 20);
Height = ranNumber2;
NoiseSize = ranNumber;
for(int x = 0; x < ChunkSize.x; x++)
{
for(int y = 0; y < ChunkSize.y; y++)
{
for(int z = 0; z < ChunkSize.z; z++)
{
GameObject box = GameObject.CreatePrimitive(PrimitiveType.Cube);
int Yscale = (int)Math.Round((PerlinNoise( x, z)), 0);
box.transform.position = new Vector3( origin+x , y+Yscale, z);
}}}}}

Add
using System;
at the top of the file.
Or use System.Math instead of Math.

It is true you could add using System. However, Unity has Mathf
Why would you rather use the built in Mathf?
System.Math uses doubles. UnityEngine.Mathf uses floats. Since most of Unity uses floats, it is better to use Mathf so that you don't have to constantly convert floats and doubles back and forth.

In ASP.NET Core, you need to get the System.Runtime.Extension package first, maybe via NuGet Package Manager in Visual Studio or by command line.
Details about the package can be found here.
Finally you need to give:
using System
And then you can use methods of this class:
using System;
namespace Demo.Helpers
{
public class MathDemo
{
public int GetAbsoluteValue()
{
var negativeValue = -123;
return Math.Abs(negativeValue);
}
}
}

Related

How can I deal with Unity job system input and output?

I am currently trying to create a script that randomly places objects such as trees, rocks, and bushes throughout my terrain (I'm using Sebastian Lague's procedural generated terrain in case your wondering.) It became quite performance intensive so I decided to try out Unity's job system. I followed a few basic tutorials and learned quite a bit, but I just can't figure out how to pass in input to the job, and then receive output. Unity keeps telling me that I can't have multiple threads change the values of the NativeArray I am sending the job. I don't really know how I would attempt to create a different NativeArray for each separate job, complete all the jobs, and then use the output from each job to complete the instantiation of the objects in the main thread.
Here is my code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst;
public class SpawnWorldObjects : MonoBehaviour
{
public WorldObject[] worldObjects;
NativeArray<bool> isTouchingOtherObject = new NativeArray<bool>(1, Allocator.TempJob);
NativeArray<Vector3> position = new NativeArray<Vector3>(1, Allocator.TempJob);
NativeArray<RaycastHit> hit = new NativeArray<RaycastHit>(1, Allocator.TempJob);
public void SpawnObjectsInChunk(Transform chunk, Vector2 sampleCenter, MeshSettings meshSettings, HeightMapSettings heightMapSettings)
{
NativeList<JobHandle> jobHandleList = new NativeList<JobHandle>(Allocator.Temp);
for (int i = 0; i < worldObjects.Length; i++)
{
for (int j = 0; j < worldObjects[i].numberOfObjectsPerChunk; j++)
{
HeightMap heightMap = HeightMapGenerator.GenerateHeightMap(meshSettings.numVertsPerLine, meshSettings.numVertsPerLine, heightMapSettings, meshSettings, sampleCenter);
CalculatePosition job = new CalculatePosition
{
sampleCenter = sampleCenter,
meshWorldSize = meshSettings.meshWorldSize,
meshScale = meshSettings.meshScale,
numVertsPerLine = meshSettings.numVertsPerLine,
minValue = heightMap.minValue,
maxValue = heightMap.maxValue,
worldObjectMinSpawnHeight = worldObjects[i].minSpawnHeight,
worldObjectMaxSpawnHeight = worldObjects[i].maxSpawnHeight,
worldObjectDistanceFromOtherObjects = worldObjects[i].distanceFromOtherObjects,
isTouchingOtherObject = isTouchingOtherObject,
position = position,
hit = hit,
};
jobHandleList.Add(job.Schedule());
}
}
JobHandle.CompleteAll(jobHandleList);
for (int i = 0; i < worldObjects.Length; i++)
{
for (int j = 0; j < worldObjects[i].numberOfObjectsPerChunk; j++)
{
if (!isTouchingOtherObject[0])
{
int typeOfObject = Random.Range(0, worldObjects[i].objectsToSpawn.Length - 1);
GameObject worldObject = Instantiate(worldObjects[i].objectsToSpawn[typeOfObject], new Vector3(position[0].x, hit[0].point.y, position[0].z), worldObjects[i].objectsToSpawn[typeOfObject].transform.rotation);
worldObject.transform.SetParent(chunk);
}
}
}
jobHandleList.Dispose();
isTouchingOtherObject.Dispose();
position.Dispose();
hit.Dispose();
}
}
[System.Serializable]
public class WorldObject
{
public GameObject[] objectsToSpawn;
public float distanceFromOtherObjects;
public int numberOfObjectsPerChunk;
[Range(0, 1)]
public float minSpawnHeight;
[Range(0, 1)]
public float maxSpawnHeight;
}
public struct CalculatePosition : IJob
{
public Vector2 sampleCenter;
public float meshWorldSize;
public float meshScale;
public int numVertsPerLine;
public float minValue;
public float maxValue;
public float worldObjectMinSpawnHeight;
public float worldObjectMaxSpawnHeight;
public float worldObjectDistanceFromOtherObjects;
public NativeArray<bool> isTouchingOtherObject;
public NativeArray<Vector3> position;
public NativeArray<RaycastHit> hit;
public void Execute()
{
float minSpawnHeight = Mathf.Lerp(minValue, maxValue, worldObjectMinSpawnHeight);
float maxSpawnHeight = Mathf.Lerp(maxValue, maxValue, worldObjectMaxSpawnHeight);
position[0] = new Vector3(Random.Range(sampleCenter.x - (float)meshWorldSize / 2, sampleCenter.x + (float)meshWorldSize / 2), 1000, Random.Range(sampleCenter.y - (float)meshWorldSize / 2, sampleCenter.y + (float)meshWorldSize / 2));
RaycastHit _hit;
if (Physics.Raycast(position[0], Vector3.down, out _hit, 10000, 1 << 7))
{
hit[0] = _hit;
if (_hit.point.y > minSpawnHeight && _hit.point.y < maxSpawnHeight)
{
RaycastHit[] hits = Physics.SphereCastAll(position[0], worldObjectDistanceFromOtherObjects, Vector3.down);
isTouchingOtherObject[0] = false;
foreach (RaycastHit __hit in hits)
{
if (__hit.collider.gameObject.layer == 9)
{
isTouchingOtherObject[0] = false;
return;
}
}
}
}
}
}
I figured it out. You have to make a list of every thing you want to do and use parallel jobs. Code Monkey on YouTube has some good content explaining this.

Mathf.PerlinNoise only returns the float 0.4652731 at every given position

I am trying to write a 2d tilemap based world generationscript but the Mathf.PerlinNoise command only returns 0.4652731!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class WorldGeneration : MonoBehaviour
{
public Tilemap Tilemap;
public Tile GrassTile;
public int width;
public int height;
public float threshold;
void Start()
{
Tilemap.ClearAllTiles();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
Debug.Log(Mathf.PerlinNoise(x, y));
if (Mathf.PerlinNoise(x, y) >= threshold)
{
Tilemap.SetTile(new Vector3Int(x, y, 0), GrassTile);
}
}
}
}
}
After executeing the script there are no errors at all! Why is the Mathf.PerlinNoise command only returning the same number?
Afaik Mathf.PerlinNoise generates a pattern with size 1 * 1. Not sure if it not even repeats.
What happens in your case I suspect is that you pass in whole numbers so it always returns the same/similar value.
Try to scale it down to fractions from 0 to 1 like e.g.
Debug.Log(Mathf.PerlinNoise(x / width, y / height));
See e.g. this post which had exactly the same issue
all of them printed the same number : 0.4652731
function Start ()
{
print(Mathf.PerlinNoise(0, 0));
print(Mathf.PerlinNoise(2, 0));
print(Mathf.PerlinNoise(0, 5));
print(Mathf.PerlinNoise(10, 3));
print(Mathf.PerlinNoise(2, 0));
print(Mathf.PerlinNoise(1, 1));
}
PerlinNoise doesn't work with integers; use floats instead, like this:
void Start()
{
Debug.Log(Mathf.PerlinNoise(1.01f, 3.45f));
}
That is because you are passing in integer values to the Mathf.PerlinNoise function. You should scale your x and y values down. Brackeys has a good tutorial on that, I recommend you to watch it.
https://www.youtube.com/watch?v=bG0uEXV6aHQ

How to use/Convert C# class in Alea?

I'm working on a RayMarching Program(HomeWork) and I want it to go faster so I use the GPU with the ALEA extension. I have a problem because I can't Use The class camera In the parallel for (GPU).
Thanks for your help.
I already tried to change the tag of the class and creating them inside the Parallel for
[GpuManaged, Test]
public static Bitmap DelegateWithClosureGpu(Scene s, Camera my_camera, SDF sdfList, int w, int h)
{
my_camera.SetScreenData(w,h);
int nbsteps;
float dyst;
Bitmap res = new Bitmap(w,h);
ParallelForTest.camera = my_camera;
Gpu.Default.For(0, res.Height , i =>
{
for (int j = 0; j < res.Height; j++)
{
Vector3 ray = ParallelForTest.camera.GetRay(i, j);
ray.Normalized();
s.RayMarch(sdfList, ray, ParallelForTest.camera.origin,out nbsteps,out dyst);
if (Scene.FloatEq(dyst,0f))
{
res.SetPixel(i,j,Color.White);
}
else
{
res.SetPixel(i,j,Color.Black);
}
}
});
return res;
}
using System;
using Alea;
namespace Raymarcher
{
[GpuManaged]
public class Camera
{
[GpuParam]
public Vector3 origin;
[GpuParam]
private Vector3 forward;
[GpuParam]
private Vector3 up;
private Vector3 right;
private Vector3 screenOrigin;
private float stepY;
private float stepX;
private float sizeX;
private float sizeY;
public Camera(Vector3 origin, Vector3 forward, float fov)
{
this.forward = forward.Normalized();
this.right=(new Vector3(-forward.z,0,forward.x)).Normalized();
this.up = (right * forward).Normalized();
this.origin = origin;
}
public void SetScreenData(int width, int height)
{
sizeY = (width / height) * sizeX;
stepX = sizeX/width;
stepY = sizeY/height;
screenOrigin = origin+forward + (up * (sizeY / 2f)) - (right * (sizeX / 2f));
}
public Vector3 GetRay(int x, int y)
{
return screenOrigin-origin+stepX*x*right-up*y*stepY;
}
}
}
and Class Vector" is only a custom class that overload operators.
You should set some variables to be the camera's variables and use them in the parallel for loop, you should also make static versions of the camera's functions and use them in the for loop.
while I'm not sure this will fix it, it's something I think you should try because you said you can't use the class camera in the parallel for and now you won't be using it in there.

Check if two lines intersect

I need to check if two lines intersect. These are currently wrapped in edge colliders.
In my minimal example i using Collider2D.OverlapsCollider
public class EdgeColliderChecker : MonoBehaviour
{
public EdgeCollider2D e1;
public EdgeCollider2D e2;
void Update () {
Collider2D[] results1 = new Collider2D[1];
e1.OverlapCollider(new ContactFilter2D(), results1);
if (results1[0] != null)
{
Debug.Log(results1[0].name);
}
Collider2D[] results2 = new Collider2D[1];
e1.OverlapCollider(new ContactFilter2D(), results2);
if (results2[0] != null) {
Debug.Log(results2[0].name);
}
}
}
This is how i have set up my scene:
As you can see in the picture above the two lines clearly intersect.
The issue is that nothing is outputed to the console.
I am not 100% sure about how ContactFilter should be configured but looking at the documentation it is used for filtering out results. So leaving it blank should include everything.
I really only need to do the check between two lines. So a function that takes them as arguments and returns a bool indicating intersection would be most convenient. Unfortunetaly I could not find such function in Unity.
It should not be overly complicated to construct the function myself but i would prefer to use the functions unity provide as much as possible. So consider this more of a unity related question than a math related one.
EDIT:
Using Collider2D.IsTouching(Collider2D) does not seem to work either. I use the same setup as before with this code instead:
public class EdgeColliderChecker : MonoBehaviour
{
public EdgeCollider2D e1;
public EdgeCollider2D e2;
void Update () {
if (e1.IsTouching(e2)) {
Debug.Log("INTERSECTION");
}
}
}
Edit 2:
I tried creating my own method for this:
public static class EdgeColliderExtentions {
public static List<Collider2D> GetInterSections(this EdgeCollider2D collider)
{
List<Collider2D> intersections = new List<Collider2D>();
Vector2[] points = collider.points;
for (int i = 0; i < points.Length - 1; i++)
{
Vector2 curr = collider.transform.TransformPoint(points[i]);
Vector2 next = collider.transform.TransformPoint(points[i + 1]);
Vector2 diff = next - curr;
Vector2 dir = diff.normalized;
float distance = diff.magnitude;
RaycastHit2D[] results = new RaycastHit2D[30];
ContactFilter2D filter = new ContactFilter2D();
Debug.DrawLine(curr, curr + dir * distance, Color.red, 1 / 60f);
int hits = Physics2D.Raycast(curr, dir, filter, results, distance);
for (int j = 0; i < hits; i++)
{
Collider2D intersection = results[j].collider;
if (intersection != collider)
{
intersections.Add(intersection);
}
}
}
return intersections;
}
}
EdgeColliderChecker:
public class EdgeColliderChecker : MonoBehaviour
{
public EdgeCollider2D e1;
void Update ()
{
List<Collider2D> hits = e1.GetInterSections();
if (hits.Count > 0) {
Debug.Log(hits.Count);
}
}
}
Still nothing. Even though the points i calculate align perfectly with the collider:
I did the math for it and it seems to work ok, not tested very thorougly. The intersection check is a bit choppy if it is run while the colliders are moving around:
public class Line {
private Vector2 start;
private Vector2 end;
public Line(Vector2 start, Vector2 end)
{
this.start = start;
this.end = end;
}
public static Vector2 GetIntersectionPoint(Line a, Line b)
{
//y = kx + m;
//k = (y2 - y1) / (x2 - x1)
float kA = (a.end.y - a.start.y) / (a.end.x - a.start.x);
float kB = (b.end.y - b.start.y) / (b.end.x - b.start.x);
//m = y - k * x
float mA = a.start.y - kA * a.start.x;
float mB = b.start.y - kB * b.start.x;
float x = (mB - mA) / (kA - kB);
float y = kA * x + mA;
return new Vector2(x,y);
}
public static bool Intersects(Line a, Line b)
{
Vector2 intersect = GetIntersectionPoint(a, b);
if (Vector2.Distance(a.start, intersect) < Vector2.Distance(a.start, a.end) &&
Vector2.Distance(a.end, intersect) < Vector2.Distance(a.start, a.end))
{
return true;
}
return false;
}
}
public static class EdgeColliderExtentions
{
public static bool Intersects(this EdgeCollider2D collider, EdgeCollider2D other)
{
Vector2[] points = collider.points;
Vector2[] otherPoints = other.points;
for (int i = 0; i < points.Length - 1; i++)
{
Vector2 start = collider.transform.TransformPoint(points[i]);
Vector2 end = collider.transform.TransformPoint(points[i + 1]);
Line line = new Line(start, end);
for (int j = 0; j < otherPoints.Length - 1; j++)
{
Vector2 otherStart = other.transform.TransformPoint(otherPoints[i]);
Vector2 otherEnd = other.transform.TransformPoint(otherPoints[i + 1]);
Line otherLine = new Line(otherStart, otherEnd);
if (Line.Intersects(line, otherLine))
{
return true;
}
}
}
return false;
}
}
But I'd really like to use something provided by unity instead.
Use Collider.bounds.Intersects(Collider.bounds) to determine if two bounds are intersecting:
void Update () {
if (e1.bounds.Intersects(e2.bounds)) {
Debug.Log("Bounds intersecting");
}
}
This unfortunately won't let you know if the edges are intersecting. However, if this tests false, you can skip testing the edges.
I realized that i could exhange one of the edge colliders for a polygon collider for my use case.
Using a polygon and an edge collider with Collider2D.OverlapsCollider() works as expected.
I don't know if i should accept this as an answer or not because it does not solve the original question about finding a funciton in unity for line intersection.
You could get a relatively close approximation with the following:
You could create a script that adds several small box colliders evenly along the line, the more the better. And then just do normal collision detection. But the more boxes (higher precision), the more costly computation-wise.

Saving a x y coordinates in a 2d vector3 array then printing the results to the console C# Unity

I'm trying to save the coordinates of placed tiles after I use a x and y loop to place them. What I would like to do is to take the coordinates of those tiles and place them in a 2d array, or save them somewhere so that when the level loads with the tiles, the coordinates of those tiles will be saved and I can use them later. I'm trying to use those points for the player, so he can travel from point to point, one step at a time.
I'm not sure if im going about it correctly and would like to be able to print the coordinates in the console to see if they were saved.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapGenerator : MonoBehaviour
{
public Transform tilePrefab;
public Vector2 mapSize;
[Range(0, 1)]
public float tileOutline;
public float[] tilePointX;
public Vector3[,] positionArray;
public Vector3 tilePosition;
void Start()
{
MapGeneratorMethod();
}
public void MapGeneratorMethod()
{
for (int x = 0; x < mapSize.x; x++)
{
for (int y = 0; y < mapSize.y; y++)
{
Debug.Log("TEST");
tilePosition = new Vector3(-mapSize.x / 2 + 0.5f + x, 0, -mapSize.y / 2 + 0.5f + y);
//getposition of tile = position array
Transform newTile = Instantiate(tilePrefab, tilePosition, Quaternion.Euler(Vector3.right * 90)) as Transform;
newTile.localScale = Vector3.one * (1 - tileOutline);
}
}
}
public void findTilePoint()
{
for (int x = 0; x < mapSize.x; x++)
{
for (int y = 0; y < mapSize.y; y++)
{
tilePosition = new Vector3(-mapSize.x / 2 + 0.5f + x, 0, -mapSize.y / 2 + 0.5f + y);
positionArray[x,y] = tilePosition;
Debug.Log(x);
}
}
// Debug.Log(x);
}
}
I would recommend you do this in a slightly different way, instead of storing the positions of the tiles in a 2D array I would stores references to the transforms of the tiles in a 2D array. i.e.
public float tileOutline;
public float[] tilePointX;
public Transform[,] tilesArray;
public Vector3 tilePosition;
void Start()
{
MapGeneratorMethod();
}
public void MapGeneratorMethod()
{
tilesArray = new transform[mapSize.x, mapSize.y];
for (int x = 0; x < mapSize.x; x++)
{
for (int y = 0; y < mapSize.y; y++)
{
Debug.Log("TEST");
tilePosition = new Vector3(-mapSize.x / 2 + 0.5f + x, 0, -mapSize.y / 2 + 0.5f + y);
//getposition of tile = position array
Transform newTile = Instantiate(tilePrefab, tilePosition, Quaternion.Euler(Vector3.right * 90)) as Transform;
newTile.localScale = Vector3.one * (1 - tileOutline);
tilesArray[x,y] = newTile;
}
}
By doing it this way you still are able to get the position of the tiles using tilesArray[x,y].GetPosition() but you will also be able to get any component connected to the tile whenever you need. also note that i added the line
tilesArray = new transform[mapSize.x, mapSize.y];
at the beginning of the function. you should really initialise the array this way before using it. As a final note you are able to pass a vector2 or vector3 directly to the debug.log as follows.
public void findTilePoint()
{
for (int x = 0; x < mapSize.x; x++)
{
for (int y = 0; y < mapSize.y; y++)
{
vector3 tilePosition = tilesArray[x,y].GetPosition()
Debug.Log(tilePosition);
}
}
// Debug.Log(x);
}

Categories

Resources