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])
Related
Hello there everybody!
I'm trying to create a variable where you can put the number of points and the radius of a circle, and it will divide those points uniformly around the circle.
I'm trying to not use the Euler angles to set rotation or the Rotate or RotateAroundmethods.
But I am not having success...
These are how my code looks until the moment
public class PowerUps : MonoBehaviour
{
public GameObject PowerUpPrefab;
public GameObject Player;
public int PowerUpCount = 3;
public float PowerUpRadius = 1;
public Vector3 newPowerupSpace;
public GameObject[] SpawnPowerUps()
{
//get player positin
Vector3 anchorPoint = Player.transform.position;
GameObject[] SpawnPowerUps = new GameObject[PowerUpCount];
float angleStep = Mathf.HalfToFloat((ushort)(360.0 / PowerUpCount));
for (int i = 0; i < PowerUpCount; i++)
{
float theta = i * angleStep;
newPowerupSpace.x = anchorPoint.x + (PowerUpRadius * Mathf.Cos(theta));
newPowerupSpace.y = anchorPoint.y + (PowerUpRadius * Mathf.Sin(theta));
SpawnPowerUps[i] = (GameObject)Instantiate(PowerUpPrefab, newPowerupSpace, Quaternion.identity);
}
return null;
}
}
Any suggestions?
Update:
I changed the
float angleStep = Mathf.HalfToFloat((ushort)(360.0 / PowerUpCount));
to
float angleStep = ((ushort)((360.0 / PowerUpCount) * Mathf.Deg2Rad));
and now is working.
I feel kind of stupid....
Update 2:
After doing some tests, I notice that some numbers don't divide uniformly across the circle. That's because I was converting de circle degrees to radium in the wrong part.
Here's how the code looks like now:
public GameObject[] SpawnPowerUps()
{
Vector3 anchorPoint = Player.transform.position;
GameObject[] SpawnPowerUps = new GameObject[PowerUpCount];
float angleStep = ((ushort)(360.0 / PowerUpCount));
for (int i = 0; i < PowerUpCount; i++)
{
float theta = i * angleStep;
newPowerupSpace.x = anchorPoint.x + (PowerUpRadius * Mathf.Cos(theta * Mathf.Deg2Rad));
newPowerupSpace.y = anchorPoint.y + (PowerUpRadius * Mathf.Sin(theta * Mathf.Deg2Rad));
SpawnPowerUps[i] = (GameObject)Instantiate(PowerUpPrefab, newPowerupSpace, Quaternion.identity);
}
return null;
}
}
To describe a circle in 3D it should have three parameters, Position, Radius and Normal. The normal can be used to create a transform from the unit circle to the 3D space. This example uses instance methods instead of static methods for cross/dot/normalization, but it should be trivial to translate to the unity3D conventions.
First we create an arbitrary vector that is orthogonal to the normal:
public static Vector3 GetOrthogonal(this Vector3 self)
{
self = self.Normalized();
if (Math.Abs(self.Dot(Vector3.UnitX)) > 0.9)
{
return self.Cross(Vector3.UnitY).Normalized();
}
return self.Cross(Vector3.UnitX).Normalized();
}
We can then create two vectors that are orthogonal to the normal, and to each other:
var xAxis = normal.GetOrthogonal();
var yAxis = xAxis.Cross(normal).Normalized();
Getting the points is then simply multiplying each coordinate with the corresponding axis:
var x = xAxis * (PowerUpRadius * Mathf.Cos(theta * Mathf.Deg2Rad));
var y = yAxis * (PowerUpRadius * Mathf.Sin(theta * Mathf.Deg2Rad));
newPowerupSpace = x + y + anchorPoint;
You could do the same by producing a transform matrix and transforming the 2D points. But this is fairly simple to do.
I am trying to build a trajectory arc that would predict the trajectory path of the object, the drag and shoot seem fine but the arc is not working. initially I used an arrow for showing the direction of the movement of the object but later I tried to do the same using an array which would store 2 points and would keep updating after every iteration and it would result in an arc since I used the equations of motion to predict the positions after each frame.
***
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement: MonoBehaviour
{
public float velocity;
float time;
float x;
float y;
float tt;
float g;
Vector2 force;
public float power = 2.0f;
Vector3 startpoint;
Vector3 endpoint;
Camera cam;
public Vector2 maxpower;
public Vector2 minpower;
public Rigidbody2D rb;
Vector3 currentposition;
Vector3 sp;
LineRenderer lr;
int resolution = 10;
Vector3 newpoint;
// Start is called before the first frame update
void Start()
{
time = 0f;
g = Mathf.Abs(Physics2D.gravity.y);
cam = Camera.main;
lr = GetComponent<LineRenderer>();
}
// Update is called once per frame
void Update()
{
time += Time.deltaTime;
x = gameObject.transform.position.x + velocity * time;
tt = time * time;
y = gameObject.transform.position.y + (g * tt) / 2f;
if(Input.GetMouseButtonDown(0))
{
startpoint = cam.ScreenToWorldPoint(Input.mousePosition);
startpoint.z = 5;
}
if(Input.GetMouseButton(0))
{
sp = new Vector3(gameObject.transform.position.x, gameObject.transform.position.y, 5);
currentposition = cam.ScreenToWorldPoint(Input.mousePosition);
currentposition.z = 5;
LineRenderer(sp);
}
if (Input.GetMouseButtonUp(0))
{
endpoint = cam.ScreenToWorldPoint(Input.mousePosition);
endpoint.z = 5;
force = new Vector2(Mathf.Clamp(startpoint.x - endpoint.x, minpower.x, maxpower.x), Mathf.Clamp(startpoint.y - endpoint.y, minpower.y, maxpower.y));
rb.AddForce(force * power, ForceMode2D.Impulse);
x = x + velocity * time;
y = y + (g * tt) / 2f;
EndLine();
}
}
public void LineRenderer(Vector3 p)
{
lr.positionCount = resolution;
Vector3 arc = p;
for(int i=0;i<resolution;i++)
{
newpoint = calculate(arc, i / (float)resolution);
lr.SetPosition(i, newpoint);
arc = newpoint;
}
}
public Vector3 calculate(Vector3 point, float t)
{
point.x += velocity * t;
point.y += 0.5f * g * t * t;
return point;
}
public void EndLine()
{
lr.positionCount = 0;
}
}
***
This the code, any help is appreciated.
A bug that I see is your delta-time:
You call Calculate(arc, i/resolution), with i and resolution both being integers.
The parameter might be float time, but C# will first calculate i/resolution as an integer division, then convert the result to float. The result will be zero as long as i is less than resolution.
Change it to: i/(float)resolution to force a floating-point division.
it's been a week since I've been trying to create, with the unity engine, an orbital system. I have found different solutions and methods but they don't satisfy the result I would like to see. Can someone tell me how to create a C# script with the addition of other details such as eccentricity?
Here is my "best" and latest code:
Orbit.cs
using UnityEngine;
using System.Collections;
public class Orbit : MonoBehaviour
{
public float axisX;
public float axisZ;
public float offsetY;
public Transform toOrbit;
public float vel = 0;
public bool clockwise;
float _vel = 0;
float timer = 0;
void Update () {
_vel = (vel / GetComponent<Rigidbody>().mass)*Time.fixedDeltaTime;
timer += _vel;
Rotate();
}
void Rotate() {
if(clockwise) {
float x = -Mathf.Cos(timer) * axisX;
float z = Mathf.Sin(timer) * axisZ;
Vector3 pos = new Vector3(x, offsetY, z);
transform.position = pos + toOrbit.position;
} else {
float x = Mathf.Cos(timer) * axisX;
float z = Mathf.Sin(timer) * axisZ;
Vector3 pos = new Vector3(x, offsetY, z);
transform.position = pos + toOrbit.position;
}
}
}
PS: I'm using Unity 5.2
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.
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() {
}
}