How to use/Convert C# class in Alea? - c#

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.

Related

Unity bullet hell line pattern

I am currently trying to make more bullet hell patterns for my game, however, I am currently stuck with making a line pattern.
I'm wanting the pattern to make a line of bullets that are at different speeds to each other so the bullets spread from each other. I know I could make several prefabs with slightly different speeds but that's inefficient with space.
The way bullets are spawned is that their rotation is set and they move forward in that direction, however, I am unsure how to set the bullets speed from another class which determines the patterns.
Here is the patterns class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletPatternsModule : MonoBehaviour
{
static ObjectPools objectPooler;
void Start()
{
objectPooler = ObjectPools.Instance;
}
public static void ShootArc(float ArcSize, int BulletAmount, string BulletName, Transform tf, float Offset)//All arcs are in angles, not radians
{
float angle = 0;
angle = Offset;//Offset is to the left
for (int i = 0; i < BulletAmount; i++)
{
float AngleStep = ArcSize / BulletAmount;//Gets the step size for arc
angle += AngleStep;
objectPooler.SpawnFromPool(BulletName, tf.position, Quaternion.Euler(0, 0, angle));//Shoots the bullet
}
}
public static IEnumerator ShootArcEnum(float ArcSize, int BulletAmount, string BulletName, Transform tf, float Offset, float LengthOfTime, float WaitPeriod)//All arcs are in angles, not radians
{
float angle = 0;
angle = Offset;//Offset is to the left
for (int i = 0; i < BulletAmount; i++)
{
float AngleStep = ArcSize / BulletAmount;
angle += AngleStep;
objectPooler.SpawnFromPool(BulletName, tf.position, Quaternion.Euler(0, 0, angle));
yield return new WaitForSeconds(WaitPeriod);
}
}
//Not quite done yet, problem
public static void ShootLine(float MinVel, float MaxVel, int BulletAmount, string BulletName, Transform tf, float angle)//All arcs are in angles, not radians
{
float Difference = MaxVel - MinVel / BulletAmount;
for (int i = 0; i < BulletAmount; i++)
{
objectPooler.SpawnFromPool(BulletName, tf.position, Quaternion.Euler(0, 0, angle));//Shoots the bullet
}
}
}
and here is the Bullet class
using UnityEngine;
public class BulletAI : MonoBehaviour, IPooledObject
{
public Transform tf;
private Vector2 Movement;
public string BulletParticle;
private float speedx;
private float speedy;
[Header("subtractive speed")]
public bool ChangeAcc;
public float AccX;
public float AccY;
public float AccMinX;
public float AccMinY;
[Header("sine wave movement")]
public bool SineMove;
public float SineAmp;
public float SineFreq;
[Header("Set up stuff")]
public float speedxMem;
public float speedyMem;
private float BulletRot;
private float ST;
private int Length;
public bool Specifics;
public bool Killable;
public string[] CollisionNames;
ObjectPools objectPooler;
void Start()
{
objectPooler = ObjectPools.Instance;
speedxMem = speedx;
speedyMem = speedy;
}
// Start is called before the first frame update
public void OnObjectSpawn()
{
if (DEBUG.ChangeGraphics == true)//CHanges sprite to toast
{
SpriteRenderer rend = gameObject.GetComponent<SpriteRenderer>();
rend.sprite = Resources.Load<Sprite>("Toast");
}
if (BulletParticle == null)
{
BulletParticle = "BulletHit";
}
speedx = speedxMem;
speedy = speedyMem;
Movement = new Vector2(speedx, speedy);
ST = 0f;//Sine phase
}
void OnTriggerEnter2D(Collider2D coll)
{
if (Specifics == true)
{
Length = CollisionNames.Length;
for (int i = 0; i < Length; i++)
{
if (coll.gameObject.CompareTag(CollisionNames[i]) && Killable)
{
objectPooler.SpawnFromPool("BulletHit", tf.position, Quaternion.identity);
gameObject.SetActive(false);
}
}
}
}
void Update()
{
Movement = new Vector2(speedx, speedy);
if (ChangeAcc)
{
speedx -= AccX * Time.deltaTime;
speedy -= AccY * Time.deltaTime;
if (speedx <= -AccMinX || speedx >= AccMinX || speedy <= -AccMinY || speedy >= AccMinY)
{
objectPooler.SpawnFromPool(BulletParticle, tf.position, Quaternion.identity);
gameObject.SetActive(false);
}
}
if (SineMove)
{
ST += Time.deltaTime;
speedy = SineAmp * Mathf.Sin(ST * SineFreq);
}
if (tf.position.x > 25f || tf.position.x < -25f || tf.position.y > 15f || tf.position.x < -15f)
{
gameObject.SetActive(false);
}
}
// Update is called once per frame
void FixedUpdate()
{
tf.Translate(Movement * Time.deltaTime);
}
}
Fixed the issue by changing the speed of the bullet in the object pooler

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.

Unity - Snap to grid while following mouse

Trying to create a Connect 4-like game. I made the board model have it's holes aligned with the grid so I can easily drop the circles into them.
Problem is I don't know how to, in unity, make the object follow the mouse while also snapping to a grid.
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LockToGrid : MonoBehaviour {
public float gridSize;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
SnapToGrid(gameObject);
}
void SnapToGrid(GameObject Object) {
var currentPos = Object.transform.position;
Object.transform.position = new Vector3(Mathf.Round(currentPos.x / gridSize) * gridSize,
currentPos.y,
currentPos.z);
}
}
I've done this before. I have these in my own math class (MathHelper). It snaps the values to multiples of another value (how far away each slot in your game is).
public static Vector3 snap(Vector3 pos, int v) {
float x = pos.x;
float y = pos.y;
float z = pos.z;
x = Mathf.FloorToInt(x / v) * v;
y = Mathf.FloorToInt(y / v) * v;
z = Mathf.FloorToInt(z / v) * v;
return new Vector3(x, y, z);
}
public static int snap(int pos, int v) {
float x = pos;
return Mathf.FloorToInt(x / v) * v;
}
public static float snap(float pos, float v) {
float x = pos;
return Mathf.FloorToInt(x / v) * v;
}
So after getting the value based on the mouse position, run it through snap, then apply the result to your GameObject's transform position. Like so:
transform.position = MathHelper.snap(Input.MousePosition, 24);
You might have to fiddle with it, if the Input.MousePosition isn't directly convertable to your coordinate space, as well as the snap distance (24 is from my own usage, yours might be 1, 5, 10, 50, or 100).

Unity 5 renderer.material.setTexture("_PARALLAXMAP"); Won't change the heightmap

So I have been working on a piece of code that generates a perlin noise texture and applies it to a plane in order to create waves. But I can't get it to set the heightmap texture of the material. I have included material.EnableKeyword("_PARALLAXMAP"); but it does nothing. I have tried this with the normal map as well, without results. Here's the full code.
using UnityEngine;
using System.Collections;
public class NoiseGenerator : MonoBehaviour {
private Texture2D noiseTex;
private float x = 0.0F;
private float y = 0.0F;
public int scale = 10;
private Color[] pixels;
public float speed;
public float move = 0.0F;
void Start () {
Renderer render = GetComponent<Renderer>();
noiseTex = new Texture2D(scale,scale);
render.material = new Material(Shader.Find("Standard"));
render.material.EnableKeyword("_PARALLAXMAP");
render.material.SetTexture("_PARALLAXMAP", noiseTex);
pixels = new Color[noiseTex.width * noiseTex.height];
}
void Update () {
float y = 0.0F;
while (y < noiseTex.height)
{
float x = 0.0F;
while (x < noiseTex.width)
{
float xCoord = move + x / noiseTex.width * scale;
float yCoord = move + y / noiseTex.height * scale;
float sample = Mathf.PerlinNoise(xCoord, yCoord);
pixels[Mathf.RoundToInt(y) * noiseTex.width + Mathf.RoundToInt(x)] = new Color(sample, sample, sample);
x++;
}
y++;
}
noiseTex.SetPixels(pixels);
noiseTex.Apply();
move = move + speed;
}
}
You need to include a Material that use this Parallax variant to notify Unity about you need this.
This can be used in the scene or include in the resource folder.
If not Unity omit this on build how unused.
Just use
ur_material.SetFloat("_Parallax",[value])

How to rotate two game objects together?

I have a game where you need to rotate clocks.I cant figure out how to rotate two or more clock arrows toghether.Arrows are not on the same clock.Arrows have diffrent rotations and they have to keep their rotation diffrences.I.E one arrow is 180 another 90 so after 90 degree turn fist one should be 270 and another one 180.Here is my code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MoveClock : MonoBehaviour
{
public GameObject root;
public Transform arrow;
public CircleCollider2D circleCollider;
public BoxCollider2D boxColliderTrigger;
public List<MoveClock> connectedClocks;
public GameManger gameManager;
public BoxCollider2D[] colliders;
public int n;
public BoxCollider2D[] disabledTriggers;
public bool equal;
const float initialValue = 90;
static public int k;
public float angle;
public float snapAngle;
public float dif;
public Vector3 mousepos;
public Vector3 dir;
public int[] zAngles;
void Start()
{
zAngles = new int[n];
SetAngles();
CalculateDiffrence();
}
void Update()
{
}
public void MoveArrow(out float snapAngle)
{
snapAngle = 0;
if (Input.GetMouseButton(0))
{
mousepos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
dir = transform.position - mousepos;
angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg + initialValue;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
snapAngle = SnapAngle(angle);
SetAngleTo(angle);
}
}
private void SetAngles()
{
int angle = 360 / n;
for (int i = 0; i < n; i++)
{
zAngles[i] = angle * i;
}
}
private float SnapAngle(float target)
{
float minDiffrence = float.MaxValue;
float closest = float.MaxValue;
for (int i = 0; i < zAngles.Length; i++)
{
float diff = Mathf.Abs(zAngles[i] - target);
if (minDiffrence > diff)
{
minDiffrence = diff;
closest = zAngles[i];
}
}
return closest;
}
public void SetAngleTo(float a)
{
for (int i = 0; i < connectedClocks.Count; i++)
{
if(equal==true)
connectedClocks[i].arrow.rotation = Quaternion.AngleAxis(a, Vector3.forward);
else
connectedClocks[i].arrow.rotation = Quaternion.AngleAxis(a + connectedClocks[i].dif, Vector3.forward);
}
}
public void CalculateDiffrence()
{
for (int i = 0; i < connectedClocks.Count; i++)
{
Vector3 dir = connectedClocks[i].transform.position - transform.position;
dir = connectedClocks[i].transform.InverseTransformDirection(dir);
dif = SnapAngle(Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg+initialValue);
Debug.Log(string.Format("{0} {1}", dif, connectedClocks[i].circleCollider.name));
}
}
}
Simply put one of the object as the child of another, that will do.
A //or B
|__B // |__A
Or programmatically:
A.transform.parent = B.transform; //or
A.transform.SetParent(B.transform);
In this setting, if you rotate A any angles, B will follow and no need to calculate and keep their angle difference in code.

Categories

Resources