Good day
I am trying to restrict my camera movement using a function that I am using to restrict other elements in a 2D game. When I call this function using my camera, it does something strange.
For some reason it does not display anything as soon as I called the function. I have tested the camera's position using Debug.log, and it seems to be in exactly the same place. The constraints also seem to work, but that is useless if nothing displays.
I am using a Mathf.Clamp function to try and constrain the map. I know that there are many tutorials showing how to constrain map movement, and honestly my approach seems similar.
I want to know why this function is failing. I am trying to keep things generic, and am already using this function to restrict the movement of other game elements.
My code looks like this:
int cameraSpeed = 10;
GameObject camera;
int maxX = 20;
int minX = -20;
int maxY = 20;
int minY = -20;
// Use this for initialization
public void constrain(GameObject obj)
{
Vector2 pos = obj.transform.position;
pos.x = Mathf.Clamp(pos.x, -maxX, maxX);
pos.y = Mathf.Clamp(pos.y, -maxY, maxY);
obj.transform.position = pos;
}
void Start () {
camera = GameObject.Find("Main Camera");
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.RightArrow))
{
camera.transform.Translate(new Vector2(cameraSpeed * Time.deltaTime, 0));
}
if (Input.GetKey(KeyCode.LeftArrow))
{
camera.transform.Translate(new Vector2(-cameraSpeed * Time.deltaTime, 0));
}
if (Input.GetKey(KeyCode.DownArrow))
{
camera.transform.Translate(new Vector2(0, -cameraSpeed * Time.deltaTime));
}
if (Input.GetKey(KeyCode.UpArrow))
{
camera.transform.Translate(new Vector2(0, cameraSpeed * Time.deltaTime));
}
Debug.Log(camera.transform.position.x);
Debug.Log(camera.transform.position.y);
constrain(camera);
}
Screenshot of game without constraints:
Screenshot of game with constraints:
I am new to Unity and am trying to understand it thoroughly. Any advice would be greatly appropriated.
The Z-position of your camera is being set to 0. All of your other objects have the same Z-position, so the camera won't render them.
Change constrain() to:
public float zPos = -10
public void constrain(GameObject obj)
{
Vector3 pos = obj.transform.position;
pos.x = Mathf.Clamp(pos.x, -maxX, maxX);
pos.y = Mathf.Clamp(pos.y, -maxY, maxY);
pos.z = zPos
obj.transform.position = pos;
}
and that should fix it.
EDIT: The reason that this is happening is because you were using a Vector2 for your camera position. In Unity, a Vector2 is a Vector3 with a z-value of 0.
I have managed to find the bug with #DerwB's assistance. I now see that the camera needs to be on a lower z index than the objects it is displaying. DerwB's answer is close to a solution, but it does not allow the function to be reused to constrain other objects.
I have thus modified the function as below:
public void constrain(GameObject obj, bool isCamera = false)
{
Vector3 pos = obj.transform.position;
pos.x = Mathf.Clamp(pos.x, -maxX, maxX);
pos.y = Mathf.Clamp(pos.y, -maxY, maxY);
if(isCamera)
pos.z = 0;
else
pos.z = 1;
obj.transform.position = pos;
}
You then call the function as follows for the camera:
GameObject camera = GameObject.Find("Main Camera");
constrain(camera.gameObject,true); //if you are constraining the camera object
And like this if you are referencing other game objects:
GameObject player= GameObject.Find("Player");
constrain(player.gameObject,true); //skip the optional parameter if not referencing the camera
Related
for a motorcycle racing game I want some parts of the track to increase the speed of the motorcycle.
I have a public float for the speed, which shows the speed in the inspector.
I added a plane with a Collider, which is a trigger and has the tag "speedfield"
Now I thought, some simple code, attached to the motorcyclescript below, would do it:
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ("speedfield")) {
Speed = Speed + 50;
}
}
But nothing happens. I think I'm missing something obvious here. Hope you can help! Greetings from germany :)
void FixedUpdate (){
Inputs();
Engine();
}
void Inputs (){
Speed = rigid.velocity.magnitude * 3.6f;
//Freezing rotation by Z axis.
transform.eulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, 0);
//If crashed...
if(!crashed){
if(!changingGear)
motorInput = Input.GetAxis("Vertical");
else
motorInput = Mathf.Clamp(Input.GetAxis("Vertical"), -1, 0);
steerInput = Input.GetAxis("Horizontal");
}else{
motorInput = 0;
steerInput = 0;
}
//Reverse bool
if(motorInput < 0 && transform.InverseTransformDirection(rigid.velocity).z < 0)
reversing = true;
else
reversing = false;
}
void Engine (){
//Steer Limit.
SteerAngle = Mathf.Lerp(defsteerAngle, highSpeedSteerAngle, (Speed / highSpeedSteerAngleAtSpeed));
FrontWheelCollider.steerAngle = SteerAngle * steerInput;
//Engine RPM.
EngineRPM = Mathf.Clamp((((Mathf.Abs((FrontWheelCollider.rpm + RearWheelCollider.rpm)) * gearShiftRate) + MinEngineRPM)) / (currentGear + 1), MinEngineRPM, MaxEngineRPM);
// Applying Motor Torque.
if(Speed > maxSpeed){
RearWheelCollider.motorTorque = 0;
}else if(!reversing && !changingGear){
RearWheelCollider.motorTorque = EngineTorque * Mathf.Clamp(motorInput, 0f, 1f) * engineTorqueCurve[currentGear].Evaluate(Speed);
}
if(reversing){
if(Speed < 10){
RearWheelCollider.motorTorque = (EngineTorque * motorInput) / 5f;
}else{
RearWheelCollider.motorTorque = 0;
}
}
}
You overriding speed variable:
void FixedUpdate (){
Inputs();
Engine();
}
void Inputs (){
Speed = rigid.velocity.magnitude * 3.6f;
...
}
change it to:
[SerializeField] float speedMultiplier = 3.6f;
[SerializeField] float speedMultiplierChange = 2;
void Inputs (){
Speed = rigid.velocity.magnitude * speedMultiplier;
...
}
and
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ("speedfield")) {
speedMultiplier += speedMultiplierChange;
}
}
Make sure that all items in this checklist are satisfied:
The motorcycle has a Rigidbody component.
The plane doesn't have a Rigidbody component (it's useless and it could slow things down).
The Mesh Collider of the plane has Convex and isTrigger set to true.
The OnTriggerEnter method is in the motorcycle script.
The thickness of the plane trigger is wide enough: if the motorcycle speed is too high, it can pass thru the plane without the physics engine being able to register the trigger.
If this is the case, try to set the Collision Detection of the motorcycle Rigidbody to Continuous and/or decrease somewhat the Fixed Timestep in the Time project settings.
Most probably the problem is due to the last two bullet points.
I'm having an issue with the cameras in Unity. When the camera moves through any means it seems to cut my FPS in half if not more. It's not really noticeable on PC, unless I'm looking at the from from 800fps to about 150fps, however on mobile it'll cut the smooth 60fps I'm getting to 20fps on a Nexus 4. It's absolutely devastating.
Here's the properties for the camera I'm using & the script HOWEVER this issue still happens without ANY of these components and a completely reset camera component:
public class ViewDrag : MonoBehaviour
{
public Vector3 hit_position = Vector3.zero;
public Vector3 current_position = Vector3.zero;
public Vector3 camera_position = Vector3.zero;
public Vector2 min_position;
public Vector2 max_position;
float z = 0.0f;
MouseHolder holder;
hider sidebarHide;
GameObject gameStructure;
// Use this for initialization
void Start()
{
gameStructure = GameObject.FindGameObjectWithTag("GameStructure");
holder = gameStructure.GetComponent<MouseHolder>();
sidebarHide = GameObject.FindGameObjectWithTag("SidebarBG").GetComponent<hider>();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
hit_position = Input.mousePosition;
camera_position = transform.position;
}
if (Input.GetMouseButton(0))
{
current_position = Input.mousePosition;
LeftMouseDrag();
}
if (!sidebarHide.isHidden)
{
//GetComponent<Camera2DFollow>().enabled = true;
}
if(gameStructure.GetComponent<ExecuteMovement2>().isExecuted)
{
//GetComponent<Camera2DFollow>().enabled = true;
}
}
void LeftMouseDrag()
{
// From the Unity3D docs: "The z position is in world units from the camera." In my case I'm using the y-axis as height
// with my camera facing back down the y-axis. You can ignore this when the camera is orthograhic.
//current_position.z = hit_position.z = camera_position.y;
// Get direction of movement. (Note: Don't normalize, the magnitude of change is going to be Vector3.Distance(current_position-hit_position)
// anyways.
Vector3 direction = Camera.main.ScreenToWorldPoint(current_position) - Camera.main.ScreenToWorldPoint(hit_position);
// Invert direction to that terrain appears to move with the mouse.
direction = direction * -1;
Vector3 position = camera_position + direction;
if (position.x < max_position.x && position.x > min_position.x && position.y < max_position.y && position.y > min_position.y)
{
if (!EventSystem.current.IsPointerOverGameObject() && holder.fromSlot == null )
{
if (sidebarHide.isHidden)
{
if (!gameStructure.GetComponent<ExecuteMovement2>().isExecuted)
{
//GetComponent<Camera2DFollow>().enabled = false;
transform.position = position;
}
}
}
}
}
}
Has anyone got an idea why this happens and how I can work around it if not fix it?
Through closer inspection I think it has something to do with the Canvas being screen space.. But it's kind of needed that way. Again, any workaround?
Check comments for profiler screenshot.
Problem Solved:
In the profiler I found that Canvas.SendWillRenderCanvases() was causing huge spikes. I solved the issue completely by turning off Pixel Perfect in the Canvas. Smooth as butter now.
As you can see in the topic - I have a camera problem. I use a script (you can see below) and I have something like this - http://rapidgamesstudio.com/games/diggermachines/
What I want to achieve is a smooth following camera to player.
I've tried everything. I have about 50-60 fps and still this bug occures.
This is my camera code:
void Update() {
if(!player)
return;
//if(!isDiggableCamera) {
Vector3 point = Camera.main.WorldToViewportPoint(player.transform.position);
Vector3 delta = player.transform.position - Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, point.z)); //(new Vector3(0.5, 0.5, point.z));
Vector3 destination = transform.position + delta;
destination.z = transform.position.z;
transform.position = Vector3.SmoothDamp(transform.position, destination, ref velocity, dampTime);
//Vector3 destination = new Vector3(player.transform.position.x, player.transform.position.y, transform.position.z);
//transform.position = Vector3.SmoothDamp(transform.position, destination, ref velocity, dampTime);
//} else {
// startDigging(0, 0, 0);
//}
leftSite.position = new Vector3(leftSite.position.x, player.position.y, leftSite.position.z);
rightSite.position = new Vector3(rightSite.position.x,
player.position.y, rightSite.position.z);
}
I tried execute this code in Update(), FixedUpdate(), LateUpdate() even with all three - and still is the same problem.
Below code for updating player position:
//move player
float changableSpeedX = 5000.0f;
float changableSpeedY = 6000.0f;
Vector2 speed = new Vector2(x * Time.deltaTime * changableSpeedX,
y * Time.deltaTime * changableSpeedY);
//if(playerRigidbody.velocity.y + speed.y >= Game.game().activeMaxVelY)
// speed.y = Game.game().activeMaxVelY - playerRigidbody.velocity.y;
playerRigidbody.AddForce(speed);
//AddForce(speed);
//and checking max speed
protected void checkSpeed()
{
if(playerRigidbody.velocity.x > Game.game().activeMaxVelX)
playerRigidbody.velocity = new Vector2(Game.game().activeMaxVelX, playerRigidbody.velocity.y);
if(playerRigidbody.velocity.x < -Game.game().activeMaxVelX)
playerRigidbody.velocity = new Vector2(-Game.game().activeMaxVelX, playerRigidbody.velocity.y);
if(playerRigidbody.velocity.y > Game.game().activeMaxVelY)
playerRigidbody.velocity = new Vector2(playerRigidbody.velocity.x, Game.game().activeMaxVelY);
if(playerRigidbody.velocity.y < maxSpeedYGravity)
playerRigidbody.velocity = new Vector2(playerRigidbody.velocity.x, maxSpeedYGravity);
}
Could anyone help me?
If you need more code please let me know which part (because I don't want to add too much unnecessary code)
Might i suggest a lerp sir , in the update function use this
maincamera.transform.position = new vector3(maincamera.transform.position,player.transform.poistion,speed*Time.deltaTime);
Try This One !!!
private float xMax;
[SerializeField]
private float yMax;
[SerializeField]
private float xMin;
[SerializeField]
private float yMin;
private Transform target;
// Use this for initialization
void Start () {
target = GameObject.Find("Player").transform;
}
// Update is called once per frame
void LateUpdate () {
transform.position = new Vector3(Mathf.Clamp(target.position.x, xMin, xMax), Mathf.Clamp(target.position.y, yMin, yMax),transform.position.z);
}
}
(Using unity3d 4.3 2d, it uses box2d like physics).
I have problems with predicting trajectory
I'm using:
Vector2 startPos;
float power = 10.0f;
float interval = 1/30.0f;
GameObject[] ind;
void Start (){
transform.rigidbody2D.isKinematic = true;
ind = new GameObject[dots];
for(int i = 0; i<dots; i++){
GameObject dot = (GameObject)Instantiate(Dot);
dot.renderer.enabled = false;
ind[i] = dot;
}
}
void Update (){
if(shot) return;
if(Input.GetAxis("Fire1") == 1){
if(!aiming){
aiming = true;
startPos = Input.mousePosition;
ShowPath();
}
else{
CalculatePath();
}
}
else if(aiming && !shot){
transform.rigidbody2D.isKinematic = false;
transform.rigidbody2D.AddForce(GetForce(Input.mous ePosition));
shot = true;
aiming = false;
HidePath();
}
}
Vector2 GetForce(Vector3 mouse){
return (new Vector2(startPos.x, startPos.y)- new Vector2(mouse.x, mouse.y))*power;
}
void CalculatePath(){
ind[0].transform.position = transform.position; //set frist dot to ball position
Vector2 vel = GetForce(Input.mousePosition); //get velocity
for(int i = 1; i < dots; i++){
ind[i].renderer.enabled = true; //make them visible
Vector3 point = PathPoint(transform.position, vel, i); //get position of the dot
point.z = -1.0f;
ind[i].transform.position = point;
}
}
Vector2 PathPoint(Vector2 startP, Vector2 startVel, int n){
//Standard formula for trajectory prediction
float t = interval;
Vector2 stepVelocity = t*startVel;
Vector2 StepGravity = t*t*Physics.gravity;
Vector2 whattoreturn = ((startP + (n * stepVelocity)+(n*n+n)*StepGravity) * 0.5f);
return whattoreturn;
}
Using this, I get wrong trajectory.
1. It's like gravity doesn't drag trajectory down at all, and yes i know that gravity is weak because:
t*t*Physics.gravity = 0.03^2 * vector2(0, -9.8) = vector2(0, -0.00882)
But that is the formula :S
2. Since gravity is low, velocity is too strong.
Here is the video:
http://tinypic.com/player.php?v=1z50w3m&s=5
Trajectory formula form:
http://www.iforce2d.net/b2dtut/projected-trajectory
What should I do?
I found that if I set
StepGravity to something stronger like (0, -0.1)
and devide startVel by 8
I get nearly right trajectory, but i don't want that, I need true trajectory path.
Users from answer.unity3d.com said I should ask here, because here is a bigger group of mathematical coders.
And I searched a lot about this problem (that how I found that formula).
you're only calculating the effect of gravity over 1/30th of a second for each step - you need to do it cumulatively. Step 1 should end with a velocity of 0.09G, Step 2 with .18G, step3 with .27G etc.
Here's a very simple example that draws the ballistic trajectory based on start velocity and a supplied time:
using UnityEngine;
using System.Collections;
public class grav : MonoBehaviour {
public Vector3 StartVelocity;
public float PredictionTime;
private Vector3 G;
void OnDrawGizmos()
{
if (G == Vector3.zero)
{
// a hacky way of making sure this gets initialized in editor too...
// this assumes 60 samples / sec
G = new Vector3(0,-9.8f,0) / 360f;
}
Vector3 momentum = StartVelocity;
Vector3 pos = gameObject.transform.position;
Vector3 last = gameObject.transform.position;
for (int i = 0; i < (int) (PredictionTime * 60); i++)
{
momentum += G;
pos += momentum;
Gizmos.DrawLine(last, pos);
last = pos;
}
}
}
In you version you'd want draw your dots where I'm drawing the Gizmo, but it's the same idea unless I'm misunderstanding your problem.
I created a object in unity
GameObject monsterclone =
(GameObject)Instantiate(monsterPrefab, floorPosition, Quaternion.identity);
This object should move in a wave style from a limit1 to limit2.
Then move back from limit2 to limit1.
Y position as well x position have to change in a specific way.
Vector3 nPos = mfloorPos + new Vector3(2f, 0f, 0f);
Vector3 oPos = mfloorPos + new Vector3(-2f, 0f, 0f);
How can I do it?
I can't exactly write the code without knowing more specific but i think this question is already asked any this link will help you out MOVE OBJECT as wave
EDIT:
I think the flat up and float down functionality will work for you for moving one point to another
example:
var floatup;
function Start(){
floatup = false;
}
function Update(){
if(floatup)
floatingup();
else if(!floatup)
floatingdown();
}
function floatingup(){
transform.position.y += 0.3 * Time.deltaTime;
yield WaitForSeconds(1);
floatup = false;
}
function floatingdown(){
transform.position.y -= 0.3 * Time.deltaTime;;
yield WaitForSeconds(1);
floatup = true;
}
example taken from
float amplitudeX = -25.0f;
float amplitudeY = 5.0f;
float omegaX = 0.5f;
float omegaY = 4.0f;
float index;
void Update () {
index += Time.deltaTime;
float x = amplitudeX*Mathf.Cos (omegaX*index);
float y = Mathf.Abs (amplitudeY*Mathf.Sin (omegaY*index));
if(transform.position.x > 24){
transform.eulerAngles = new Vector3(270, -90, 0);
}
if(transform.position.x < -24){
transform.eulerAngles = new Vector3(270, 90, 0);
}
transform.localPosition= new Vector3(x,y,20);
}
If this is a consitant wave and not dependant on speed I would use an animation to create a literal wave curve of the Position.Y value (much in the same principle as Ravindra Shekhawat has explained.) you can find out more about animation here.
Here is some code (untested) that you could go off. It is in c# so I hope it proves no issue with putting in to JavaScript.
bool monsterMoving = false;
void Update(){
//check monster moving to start updating position
if(monsterMoving == true){
//moving animation controls up and down "wave" movement
animation.CrossFade('moving');
//Lerp changes position
Transform.Lerp(transform.Position, oPos, Time.deltaTime);
if (transform.Position == oPos) {
//We are at destination, stop movement
monsterMoving = false;
}
} else {
// if monster stopped moving, return to idle animation (staying still)
animation.CrossFade('idle');
}
}
// function to send a new position to the monster object
void MoveTo(Vector3 newPos){
oPos = newPos;
monsterMoving = true;
}