I have a cube which i am moving in circle shape (with horizontal key input) is below code suggested.
public class Oscillator : MonoBehaviour {
float timeCounter = 0;
float speed,width, height;
public float yPosition = 30;
// Use this for initialization
void Start () {
speed = 2; width = 10; height = 10;
}
// Update is called once per frame
void Update () {
timeCounter += Time.deltaTime * speed * Input.GetAxis("Horizontal");
float x = Mathf.Sin (timeCounter)* height;
float y = yPosition;
float z = Mathf.Cos (timeCounter) * width;
transform.position = new Vector3 (x, y, z);
}
}
Now my object is moving in circular shape which is fine. Now i want to translate my objects movement into time.
Let suppose
if my object x position is 1 then it should give me time 1.0
if it is 1.5 then it should give me 1.5
it increase or decrease according to x postion of my object (or possibly throught z).
I logged my object's x position which is starting from 0 to 9.999 and then become decrease 0, then -1 to -9 then it become decrease 0 and reached to its initial position. This circular movement x values are strange for me, i am unable to form any formula that can convert my x position into time.
Please can any one help me in this purely mathematics and 3d math problem?
You could try the following:
Get the vector between origin of the circle and the 0 of your circle, like 12 on a clock. This one is constant.
Then you have the vector between the origin of the circle and the current point.
Try the following:
Vector3 from = new Vector3(0,0,1); / This is your 12
Vector3 to = GetCurrentVector();
float angle = Quaternion.FromToRotation(Vector3.up, to - from).eulerAngles.z;
Debug.Log(angle / 360f);
Related
everyone!
I ran into the problem. I need to draw a radius of enemy attack. The radius needs to be equal radius of SphereCollider that is hanging on it. I've tried to do it with the help of LineRenderer which draws circle. Yeah, actually it draws circle correctly, but the radius of my circle is less than radius of collider on it, despite the fact that I've given the value of a variable from the GetComponent().
Does anyone know what the problem is?
Part of my code:
float x;
float z;
float change = 2 * (float)Math.PI / segments;
float angle = change;
x = Mathf.Sin(angle) * radius;
_line.SetPosition(0, new Vector3(x, 0, Mathf.Cos(angle) * radius));
for (int i = 1; i < (segments + + 2); i++)
{
x = Mathf.Sin(angle) * radius;
z = Mathf.Cos(angle) * radius;
yield return new WaitForSeconds(drawSpeed);
_line.SetPosition((int)i, new Vector3(x, 0, z));
angle += change;
}
In the comments you mentioned that you get your radius from
float radius = _collider.radius;
where _collider is your SphereCollider.
So note that the SphereCollider.radius
The radius of the sphere measured in the object's local space.
The sphere radius will be scaled by the transform's scale.
It appears to me that either your object or one of its parent is somehow scaled differently than 1,1,1 in which case the actual final radius will be influenced by that scale.
You would need to scale the radius accordingly by the transform.lossyScale like e.g.
// Get the lossyScale
// this is the localScale of all parent objects and this localScale combined
var lossyScale = _collider.transform.lossyScale;
// find the biggest extends of the lossyScale
// if you already know they are always equal anyway simply use e.g. lossyScale.x instead
float maxScale = 0;
for(var i = 0; i < 3; i++)
{
maxScale = Mathf.Max(maxScale, Mathf.Abs(lossyScale[i]);
}
float radius = _collider.radius * maxScale;
It's a little hacky, but I've used a sphere outline sprite for just this sort of thing. Just put it on the game object and make sure it is scaled same as your collider. No need for fancy line drawing.
Don't use collider component for the enemy attack range!
Instead of adding a circle collider component you should a collider via code & physics.
What should you do?
This is an example of using a collider via code & physics:
float theCircleRadios = /* You radios */;
Collider2D[] detectedEnemiesColliders = Physics2D.OverlapCircleAll(theCirclePosition, theCircleRadios, DetectedLayers);
Then make your line lineRenderer radios == theCircleRadios.
An example of my code, lets say I have a solar system, center being the sun, this code will spawn all the planets around it randomly with a set radius for each planet, in the Vector3 I change and randomize the X and Z, leaving Y at 0.
This is the code, planetInt is the number of planet in the for loop, 0 being first planet up to the 8 planet.
private float orbitRadius = 3150f;
// Get Radius
float newOrbitRadius = orbitRadius * (planetInt + 1);
// Get Random Positon (here)
Vector3 randomPlanetPosition = new Vector3(Random.insideUnitSphere.x * newOrbitRadius, 0, Random.insideUnitSphere.z * newOrbitRadius);
How would I change the Vector3( X and Z) to be in a specific zone, for example I want all the positions to be in the same area like this picture.
How do specify a specific angle like the multiple ones in this image, with Y being 0.
Here is an example:
I created this script:
(I suppose your sun is at the center 0;0;0)
public class NewBehaviourScript : MonoBehaviour
{
public GameObject PlanetPrefab = null;
public int numPlanets = 20;
public float orbitLengthBase = 0.3f;
public float angleMin = 45f;
public float angleMax = 120f;
void Start()
{
for (int i = 0; i < numPlanets; i++)
{
var newPlanet = Instantiate(PlanetPrefab);
var randomRotationAngle = Random.Range(angleMin, angleMax);
var rotation = Quaternion.Euler(0, randomRotationAngle, 0);
newPlanet.transform.position = rotation * Vector3.right * orbitLengthBase * i;
}
}
}
I always assign an arbitrary base vector (here: pointing to the right, (1;0;0)) as the position of the new planet, I multiply it by some factor the change the distance from sun just for the example.
More importantly, I multiply it on the left by a quaternion (math thing to represent a rotation), that I just created with a random Y angle between the max and the min that you want.
You can play with some parameters like angleMax and angleMin to see by yourself.
Any tips on how to move an object back and forth sinusoidally (like a pendulum, but in a linear path) along a specified 3D vector? I've got the sinusoidal motion and the vector, but I can't figure out how to combine the two.
The following are the two pieces of code I have; the vector is specified using angles from the origin.
I'm very new to coding, so please forgive me for any mistakes in the code.
This moves the object in the sinusoidal path about the origin - this is the motion I want to achieve along the 3D vector.
float rodPositionZsin = pathLength * Mathf.Sin(Time.time) + position;
transform.position = new Vector3(0, 0, rodPositionZsin);
This will move the object along the vector in the X and Y dimensions, but I'm stumped for what to do in the Z.
float Xangle = 20;
float Yangle = 50;
float Zangle = 30;
//Position Transformations
float rodPositionZsin = pathLength * Mathf.Sin(Time.time) + position;
float rodPositionY = Mathf.Cos(Yangle*Mathf.PI/180)*pathLength;
float rodPositionX = Mathf.Sin(Xangle * Mathf.PI / 180)*pathLength;
float rodPositionZ = Mathf.Tan(Zangle * Mathf.PI / 180) * pathLength;
transform.position = Vector2.MoveTowards(transform.position, new Vector2(rodPositionX, rodPositionY), pathLength * Mathf.Sin(Time.time));
rodPositionX = transform.position.x;
rodPositionY = transform.position.y;
rodPositionZ = rodPositionZsin + transform.position.z;
transform.position = new Vector3(rodPositionX, rodPositionY, rodPositionZsin);
if you have a vector, you just need to scale it by a sine curve, then set the object's position to that scaled vector.
so in (untested) pseudocode:
Vector3 scaledVector = originalVector* Mathf.Sin(Time.time);
youGameObject.transform.position = scaledVector
You can then add phase, frequency, and amplitude terms in your sine function to change the frequency of oscillation, how far along that vector, and the start position of the oscillation if you want to customize it further.
Edit:
Here’s how to add these.
http://jwilson.coe.uga.edu/EMT668/EMT668.Folders.F97/Feller/sine/assmt1.html
a * sin(b*x +c) + offset.
Where a is amplitude (max distance travelled)
B is wavelength (1/frequency of oscillation)
C is phase ( starting pos) and offset is to move the whole oscillation pattern along the vector ( make it happen away from origin center)
I'm trying to write a script in Unity which creates a type of radial menu around an object the player is directly facing, but the number of buttons in the menu is a variable.
I've generated the angles to the main menu the objects are supposed to appear at easily enough...
// int buttonCount = number of buttons
float buttonWidth = 360 / buttonCount;
for (int i = 1; i <= buttonCount; i++)
{
float maxAngle = buttonWidth * i;
float minAngle;
if (i == 0)
{
minAngle = 0f;
}
else if (i == buttonCount)
{
minAngle = 360 - buttonWidth;
}
else
{
minAngle = buttonWidth * (i - 1);
}
float buttonAngle = (minAngle + maxAngle) / 2;
}
...but now I'm trying to position the button objects at the corresponding angles around the central menu object and I don't know how?
This function takes as parameters the object you want the buttons to go around, the player gameobject so that you can orient the new buttons toward the player, the angle you want the button to be at, and the radius (distance the button will be from the buttonCenter). Its output is the button position in world space. You can call it for each button you want to add.
Vector3 positionButton(GameObject buttonCenter, GameObject player, float angle, float radius) {
//get the up and right vectors from the player object so we can orient the buttons
Vector3 up = player.transform.up;
Vector3 right = player.transform.right;
angle = Mathf.Deg2Rad * angle; //convert degrees to radians. radians=degrees * 2pi / 360
//cos(angle) give an x coordinate, on a unit circle centered around 0
//sin(angle) is the y coordinate on the unit circle
//take those values, multiply them by the up and right vectors to orient them to the player,
//multiply by the radius to move them the correct distance from the buttoncenter,
//and add the buttoncenter position so they circle around the correct point
Vector3 buttonPos =buttonCenter.transform.position + (radius * right * Mathf.Cos(angle)) + (radius* up * Mathf.Sin(angle));
return buttonPos;
}
First, define an origin and distance for each button from it. As you have the angles, you can apply trigonometry which should allow you to find the coordinate of a point given an angle, distance and origin point. The point will be defined by cos() and sin() of the angle.
Have a look at the 2nd section here
I have a 2D game in unity, and I have a camera that follow my main character.
Currently, when I, for example, move the character to the left, I can see what's beyond the map, like so:
Say the map size is 15X15. I have a script generating 15X15 blocks of size 1X1, meaning the map bounds are (-1, -1) -> (15, 15).
There are two things I want to accomplish:
1) Have the camera not go out of the map bounds
2) When the map size is SMALLER than the camera, have the camera change its size.
Example for point 2)
The map is 5 columns and 15 rows, thus it's very narrow compared to the camera, like so:
or even 10 columns and 3 rows, like so:
I would want the size of the camera to change so it won't be neither wider or taller than the map.
How do I do those two things?
This is the github to the current scripts in the game. The CameraController script is where the additions are supposed to be
The orthographic size defines half of the vertical size, the horizontal size is based on aspect ratio.
From there you can define what should be the biggest value when centered.
The script below should get you going. As long as your level are rectangle (that obviously includes square), it will go fine:
public float speed = 2f;
public Transform min;
public Transform max;
private float aspect;
private float maxSize;
private void Start ()
{
this.aspect = Camera.main.aspect;
this.maxSize = max.position.x <= max.position.y ? max.position.x /2f / this.aspect :max.position.y / 2f;
}
private void Update ()
{
float size = Input.GetAxis ("Mouse ScrollWheel");
Camera.main.orthographicSize += size;
if (Camera.main.orthographicSize > maxSize)
{
Camera.main.orthographicSize = maxSize;
}
float x = Input.GetAxis ("Horizontal");
float y = Input.GetAxis ("Vertical");
Vector3 position = this.transform.position;
position.x += x * Time.deltaTime * this.speed;
position.y += y * Time.deltaTime * this.speed;
float orthSize = Camera.main.orthographicSize;
if (position.x < (this.min.position.x + orthSize * this.aspect))
{
position.x = this.min.position.x + orthSize * this.aspect;
}
else if (position.x > (this.max.position.x - orthSize * this.aspect))
{
position.x = this.max.position.x - orthSize * this.aspect;
}
if (position.y < (this.min.position.y + orthSize))
{
position.y = this.min.position.y + orthSize;
}
else if(position.y > (this.max.position.y - orthSize))
{
position.y = this.max.position.y - orthSize;
}
this.transform.position = position;
}
the idea is that you have two empty game objects place at bottom left and upper right. Bottom left is dragged into min and upper right goes int max. The speed variable is just how fast the camera translates. This is attached to the camera object. There is no limit for min size of camera, but you can do it.
The point is just that you get this going for your own project as this is more generic.
The rest is just considering the camera position, current size and aspect ratio (you cannot change that at runtime or you'd have to modify the code).
EDIT:
If you wish to bound the camera zoom to the movement,remove the first lines about size and add the following after you get the horizontal/vertical movement:
if (x != 0f || y != 0f) {
Camera.main.orthographicSize = Mathf.MoveTowards (Camera.main.orthographicSize, largeSize, Time.deltaTime);
} else {
Camera.main.orthographicSize = Mathf.MoveTowards (Camera.main.orthographicSize, size, Time.deltaTime);
}
Think of declaring the size, largeSize variables and set them to your need.