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).
Related
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.
I'm making a script which should rotate a GameObject like a joystick, which means that only X and Z axes must change. So i'm using sin and cos functions to calculate rotation angles. But for some reason Y axis changes as well.
public float alpha;
void Update () {
alpha += Time.deltaTime;
var x = R * Mathf.Cos(alpha);
var z = R * Mathf.Sin(alpha);
transform.Rotate(new Vector3(x, 0, z) * Time.deltaTime);
}
So the question is how do I stop Y axis from changing or maybe there is another way to rotate the object like a joystick.
P.S. I am using Unity 2017.4.13f1
In your update function you may write :
public float alpha;
public Vector3 rotation;
void Start(){
rotation = transform.rotation.eulerAngles;
}
void Update () {
alpha += Time.deltaTime;
var x = Mathf.Cos(alpha);
var z = Mathf.Sin(alpha);
rotation.x = x;
rotation.z = z;
transform.rotation = Quaternion.Euler(rotation*time.deltaTime);
}
I couldn't understand the R variable that you multiplied with Sin and Cos. where is that R defined???
I decided to set Y axis to 0 every frame. Maybe not the most elegant solution but it works just as I needed.
Vector3 rotationVector;
void Start()
{
rotationVector = new Vector3();
}
private float alpha;
public float multiplier;
void Update ()
{
alpha += Time.deltaTime;
rotationVector.x = Mathf.Cos(alpha);
rotationVector.z = Mathf.Sin(alpha);
transform.Rotate(multiplier * rotationVector * Time.deltaTime);
transform.eulerAngles = new Vector3(transform.eulerAngles.x, 0, transform.eulerAngles.z);
}
So I have this function attached to a sphere and in inverse one attached to another. They are rigged to emit a trail and the game object they are orbiting around is a sphere which is locked at 0,0,0. This is my code so far :
float t = 0;
float speed;
float width;
float height;
int cat = 0;
public GameObject orbit; //the object to orbit
// Use this for initialization
void Start()
{
speed = 2;
width = 5;
height = 2;
InvokeRepeating("test", .001f, .009f);
}
void test()
{
t += Time.deltaTime * speed;
Vector3 orbitv = orbit.transform.position;
float inc = .0000000001f;
inc += inc + t;
float angmom = .00001f;
angmom = angmom + t;
float x = orbitv.x + Mathf.Cos(t);
float z = orbitv.z + inc; //+ (Mathf.Cos(t)*Mathf.Sin(t));
float y = orbitv.y + Mathf.Sin(t);
transform.position = new Vector3(x, y, z);
}}
Which does this:
Instead of moving in the z direction exclusively, I'd like them to continue their current rotation, but in a circle around the sphere at 0,0,0 while staying at the same y level. Anyone have any ideas how I can do this?
Edit: This is what I'm trying to do:
Here's some code I cooked up for you.
All the movement is achieved with basic trigonometric functions and some easy vector math.
To tackle problems like these, try to break things down like I did with dividing the movement into circular/up-down & sideways. This lets you create the ring effect.
Adding more intertwined waves should be trivial by changing the phase of the oscillations and adding more trails.
public class Orbit : MonoBehaviour {
float t = 0;
public float speed;
public float width;
public float height;
public float radius;
int cat = 0;
public GameObject center; //the object to orbit
public Vector3 offset;
void Update()
{
t = Time.time * speed;
OrbitAround();
AddSideways();
}
void OrbitAround()
{
float x = radius * Mathf.Cos(t);
float y = Mathf.Sin(offset.y * t);
float z = radius * Mathf.Sin(t);
transform.position = new Vector3(x, y, z);
}
void AddSideways()
{
float x = Mathf.Cos(offset.x * t);
Vector3 dir = transform.position - center.transform.position;
transform.position += dir.normalized * x;
}
}
It should give you a trail like this:
You can play around with the Vec3 offset which changes the frequency of the oscillations and essentially lets you choose the number of rings.
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])
Im trying to get the hex prefab shapes that have already been created to line up with one another in a grid formation. I got the grid but I can't seem to get the hexes to fit into each other. Fixed the y%2 but the way it is setup now it crashes.
using UnityEngine;
using System.Collections;
public class boardObject : MonoBehaviour {
// Instantiates a prefab in a grid
public GameObject prefab;
public float gridX = 5f;
public float gridY = 5f;
public float spacing = 2f;
void Start() {
for (float y = 0.0f; y < gridY; y++) {
for (float x = 0.0f; x < gridX; x++) {
// THIS IS WHAT WAS MISSING FOR THIS TO ACTUALLY WORK MAKING A NEW VECTOR 3
// POSITION AFTER THE LOOP WAS SET UP. EACH NEW hex NEEDED HAVE A NEW POSITION. ->
Vector3 pos = new Vector3(x, 0.0f, y) * spacing;
//
//
//%2 thingy
if (y%2.0f==0.0f)
gridY += 0.5f;
else
gridY -= 0.0f;
Instantiate(prefab, pos, Quaternion.identity);
}
}
}
}
First pic is the one I have, second is the one I am trying to make.
This is the square board hex
This is what I am trying to do
using UnityEngine;
using System.Collections;
public class boardObject : MonoBehaviour {
// Instantiates a prefab in a grid
public GameObject prefab;
public float gridX = 5f;
public float gridY = 5f;
public float spacing = 2f;
public float xsize = 1.0f;
public float ysize = 1.0f;
void Start() {
for (float y = 0; y < gridY; y++) {
for (float x = 1; x < gridX; x++) { //<<<<<This is where the change was made to get it to work. x = 1 instead of 0.
Vector3 pos = new Vector3 (x * xsize, 0.0f, y * ysize) ;
Instantiate (prefab, pos, Quaternion.identity);
if (y % 2 == 0)
y += 1;
else
y -= 1;
}
}
}
void Update() {
}
}