How to make the camera follow the character without dragging the background along with it in screen space camera render mode in Unity? - unity3d

I am making a 2D platfomer and I am using screen space-camera render mode in canvas. Now the background fits inside the screen in every aspect ratio perfectly. But when I make the camera follow the character, the background also comes with it, making the character look like it is not moving.
Code for player movement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
private Rigidbody2D myRigidbody;
[SerializeField]
private float movementSpeed;
// Use this for initialization
void Start ()
{
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void FixedUpdate ()
{
float horizontal = Input.GetAxis ("Horizontal");
HandleMovement(horizontal);
}
private void HandleMovement(float horizontal)
{
myRigidbody.velocity = new Vector2 (horizontal * movementSpeed, myRigidbody.velocity.y);
}
}
Here is the camera follow code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public Transform target;
Vector3 velocity = Vector3.zero;
public float smoothTime = 0.15f;
public bool YMaxEnabled = false;
public float YMaxValue = 0;
public bool YMinEnabled = false;
public float YMinValue = 0;
public bool XMaxEnabled = false;
public float XMaxValue = 0;
public bool XMinEnabled = false;
public float XMinValue = 0;
void FixedUpdate()
{
Vector3 targetPos = target.position;
//vertical
if (YMinEnabled && YMaxEnabled)
{
targetPos.y = Mathf.Clamp (target.position.y, YMinValue, YMaxValue);
}
else if (YMinEnabled)
{
targetPos.y = Mathf.Clamp (target.position.y, YMinValue, target.position.y);
}
else if (YMaxEnabled)
{
targetPos.y = Mathf.Clamp (target.position.y, target.position.y, YMaxValue);
}
//horizontal
if (XMinEnabled && XMaxEnabled)
{
targetPos.x = Mathf.Clamp (target.position.x, XMinValue, XMaxValue);
}
else if (YMinEnabled)
{
targetPos.x = Mathf.Clamp (target.position.x, XMinValue, target.position.x);
}
else if (YMaxEnabled)
{
targetPos.x = Mathf.Clamp (target.position.x, target.position.x, XMaxValue);
}
targetPos.z = transform.position.z;
transform.position = Vector3.SmoothDamp (transform.position, targetPos, ref velocity, smoothTime);
}
}

If you use screen space camera, then the Canvas will move with the camera. I would suggest using Sprite Renderer instead of Canvas panel for level background. If you need to scale the Sprite according to screen, do it from the code. Also, for scrolling the background, you can follow this tutorial:
https://unity3d.com/learn/tutorials/topics/2d-game-creation/2d-scrolling-backgrounds

Related

How to Jump by Button UI using Character Controller in Unity3D

I am calling JUMP function from a UI Button but unable to jump using Character Collider provided by Unity. Can someone please help me where am i going wrong?
PlayerMovement Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class PlayerControllerCC : MonoBehaviour
{
public FixedJoystick moveJoystick;
CharacterController _charController;
private Vector3 v_movement;
private Animator _animator;
public float moveSpeed = 0.1f;
public float gravity = 0.5f;
public float jumpForce = 0.5F;
private float originalstepOffset;
private float InputX;
private float InputZ;
// Start is called before the first frame update
void Start()
{
moveSpeed = 0.1f;
gravity = 0.5f;
jumpForce = 0.5F;
_charController = GetComponent<CharacterController>();
originalstepOffset = _charController.stepOffset;
_animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
InputX = moveJoystick.Horizontal;
InputZ = moveJoystick.Vertical;
isWalking();
}
private void FixedUpdate()
{
playerMovement();
}
void playerMovement()
{
//Check Gravity
if (_charController.isGrounded)
{
_charController.stepOffset = originalstepOffset;
v_movement.y = -0.5f;
}
else
{
_charController.stepOffset = 0;
v_movement.y -= gravity * Time.deltaTime;
}
//player movement
v_movement = new Vector3(InputX * moveSpeed, v_movement.y, InputZ * moveSpeed);
float magnitute = Mathf.Clamp01(v_movement.magnitude);
v_movement.Normalize();
_charController.Move(v_movement * magnitute);
Vector3 lookDir = new Vector3(v_movement.x, 0, v_movement.z);
//Set rotation facing after player movement
if ((lookDir.x != 0) && (lookDir.z != 0))
{
transform.rotation = Quaternion.LookRotation(lookDir);
}
}
void isWalking()
{
if (InputX == 0 && InputZ == 0)
{
_animator.SetBool("isWalking", false);
}
else
{
_animator.SetBool("isWalking", true);
}
}
public void Attack()
{
_animator.SetTrigger("isAttacking");
}
public void Jump()
{
if (_charController.isGrounded)
{
v_movement.y = jumpForce * Time.deltaTime;
}
}
}
When button is clicked in UI it called the JUMP function. I am not using keyboard but FixedJoyStick hence using button to jump.
My Game looks like this and the UI. The up arrow key is the jump button.
The Game button Up Arrow Jump
Calling Jump Function in Button
Your problem lays on the OnClick() function of the button, it is interacting with the script but the script itself is not attached to any character in this case. What you did works when the script works by itself no matter where is attached (e.g. when you call all the objects with a tag).
What you need to do is to link the object which has the script to the OnClick() in the editor, then select from the dropdown menu the script component and then call the function you want.
Like This.
Image link since I'm new
Notice how what is linked are the Game Objects and then the script is selected.

Jump in using Rigidbody or Character controller

i have been recreating my jump code, i have it all done but i can't add force or anything else.
Here's my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class pBeh : MonoBehaviour
{
CharacterController characterController;
public float MovementSpeed = 1;
public float Gravity = 9.8f;
private float velocity = 0;
private Camera mainCam;
public Rigidbody rb;
public float jumpSpeed = 5.2f;
private Vector3 movingDirection = Vector3.zero;
public CharacterController controller;
public float speed;
float turnSmoothVelocity;
public float turnSmoothTime;
public bool canJump = false;
private void Start()
{
characterController = GetComponent<CharacterController>();
mainCam = Camera.main;
}
void Update()
{
// player movement - forward, backward, left, right
float horizontal = Input.GetAxis("Horizontal") * 10;
float vertical = Input.GetAxis("Vertical") * 10;
Vector3 camRightFlat = new Vector3(mainCam.transform.right.x, 0,
mainCam.transform.right.z).normalized;
Vector3 camForwardFlat = new Vector3(mainCam.transform.forward.x, 0,
mainCam.transform.forward.z).normalized;
characterController.Move((camRightFlat * horizontal + camForwardFlat * vertical)
* Time.deltaTime);
// Gravity
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
if (canJump == true && Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Jumped");/*
transform.Translate(Vector3.up * 5.0f * Time.deltaTime);
rb.AddRelativeForce(Vector3.up * 8.0f);
rb.AddForce(Vector3.up * 8.0f)
i have tried a lot more, but it just doesn't work.
The sphere (Player) does nothing or shakes.
*/
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "enemy")
{
SceneManager.LoadScene("SampleScene");
}
}
void FixedUpdate()
{
if ((controller.collisionFlags & CollisionFlags.Below) != 0)
{
//Debug.Log("ground");
canJump = true;
}
else
{
canJump = false;
}
}
As i said it works just fine i just can't find reason why i cannot jump.
I have all character controller right and rigidbody too. If you could help i would be happy.
Btw i am beginner so i copied movement to be same as camera. Thanks!
From what I know, rigidbody and character controller do not work together (on the same object) so you have to choose one or the other, if you are using rigidbody then a ground check or similiar stuff would not be necessary since rigidbody is using unity physicis system so a lot of the stuff would be already done for you to simulate physics but you should still read thru the document

Unity 2D player movement

I had my unity movement working on my computer, however when i try to play on my android it is not moving for me at all. I am sure it is probably a small error i am overlooking but i would be very appreciative of any help! I do not get any errors when i try yo run my code if that is of any assistance! I will supply the code below:
using UnityEngine;
using System.Collections;
//Adding this allows us to access members of the UI namespace including Text.
using UnityEngine.UI;
public class PlayerControler : MonoBehaviour {
public Text countText; //Store a reference to the UI Text component which will display the number of pickups collected.
//public Text winText; //Store a reference to the UI Text component which will display the 'You win' message.
private double count; //Integer to store the number of pickups collected so far.
//Player movement controls
private Vector3 touchPosition; //where your finger touches screen
private Vector3 direction; //direction you drag sprite
private Rigidbody2D rb2d; //Store a reference to the Rigidbody2D component required to use 2D Physics.
public float speed = 10f; //Floating point variable to store the player's movement speed.
// Use this for initialization
void Start()
{
//Get and store a reference to the Rigidbody2D component so that we can access it.
rb2d = GetComponent<Rigidbody2D> ();
//Initialize count to zero.
count = 0;
//Initialze winText to a blank string since we haven't won yet at beginning.
//winText.text = " "; //error here??
//Call our SetCountText function which will update the text with the current value for count.
//SetCountText ();
}
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
touchPosition = Camera.main.ScreenToWorldPoint(touch.position);
touchPosition.z = 0;
direction = (touchPosition - transform.position);
rb2d.velocity = new Vector2(direction.x , direction.y) * speed;
if(touch.phase == TouchPhase.Ended)
{
rb2d.velocity = Vector2.zero;
}
}
}
//OnTriggerEnter2D is called whenever this object overlaps with a trigger collider.
void OnTriggerEnter2D(Collider2D other)
{
//Check the provided Collider2D parameter other to see if it is tagged "PickUp", if it is...
if (other.gameObject.CompareTag ("PickUp"))
{
//... then set the other object we just collided with to inactive.
other.gameObject.SetActive(false);
//Add one to the current value of our count variable.
count = count + 1;
//Update the currently displayed count by calling the SetCountText function.
//SetCountText ();
}
}
Here is my 2D Player Movement Controller.
Code(Character Controller) -
using UnityEngine;
using UnityEngine.Events;
public class CharacterController2D : MonoBehaviour
{
[SerializeField] private float m_JumpForce = 400f; // Amount of force added when the player jumps.
[Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f; // Amount of maxSpeed applied to crouching movement. 1 = 100%
[Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f; // How much to smooth out the movement
[SerializeField] private bool m_AirControl = false; // Whether or not a player can steer while jumping;
[SerializeField] private LayerMask m_WhatIsGround; // A mask determining what is ground to the character
[SerializeField] private Transform m_GroundCheck; // A position marking where to check if the player is grounded.
[SerializeField] private Transform m_CeilingCheck; // A position marking where to check for ceilings
[SerializeField] private Collider2D m_CrouchDisableCollider; // A collider that will be disabled when crouching
const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
private bool m_Grounded; // Whether or not the player is grounded.
const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up
private Rigidbody2D m_Rigidbody2D;
private bool m_FacingRight = true; // For determining which way the player is currently facing.
private Vector3 m_Velocity = Vector3.zero;
[Header("Events")]
[Space]
public UnityEvent OnLandEvent;
[System.Serializable]
public class BoolEvent : UnityEvent<bool> { }
public BoolEvent OnCrouchEvent;
private bool m_wasCrouching = false;
private void Awake()
{
m_Rigidbody2D = GetComponent<Rigidbody2D>();
if (OnLandEvent == null)
OnLandEvent = new UnityEvent();
if (OnCrouchEvent == null)
OnCrouchEvent = new BoolEvent();
}
private void FixedUpdate()
{
bool wasGrounded = m_Grounded;
m_Grounded = false;
// The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
// This can be done using layers instead but Sample Assets will not overwrite your project settings.
Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].gameObject != gameObject)
{
m_Grounded = true;
if (!wasGrounded)
OnLandEvent.Invoke();
}
}
}
public void Move(float move, bool crouch, bool jump)
{
// If crouching, check to see if the character can stand up
if (!crouch)
{
// If the character has a ceiling preventing them from standing up, keep them crouching
if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround))
{
crouch = true;
}
}
//only control the player if grounded or airControl is turned on
if (m_Grounded || m_AirControl)
{
// If crouching
if (crouch)
{
if (!m_wasCrouching)
{
m_wasCrouching = true;
OnCrouchEvent.Invoke(true);
}
// Reduce the speed by the crouchSpeed multiplier
move *= m_CrouchSpeed;
// Disable one of the colliders when crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = false;
}
else
{
// Enable the collider when not crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = true;
if (m_wasCrouching)
{
m_wasCrouching = false;
OnCrouchEvent.Invoke(false);
}
}
// Move the character by finding the target velocity
Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
// And then smoothing it out and applying it to the character
m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref m_Velocity, m_MovementSmoothing);
// If the input is moving the player right and the player is facing left...
if (move > 0 && !m_FacingRight)
{
// ... flip the player.
Flip();
}
// Otherwise if the input is moving the player left and the player is facing right...
else if (move < 0 && m_FacingRight)
{
// ... flip the player.
Flip();
}
}
// If the player should jump...
if (m_Grounded && jump)
{
// Add a vertical force to the player.
m_Grounded = false;
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
}
}
private void Flip()
{
// Switch the way the player is labelled as facing.
m_FacingRight = !m_FacingRight;
// Multiply the player's x local scale by -1.
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
And here is the actual Character Movement Code -
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController2D controller;
public float runSpeed = 40f;
float horizontalMove = 0f;
bool jump = false;
private void Update()
{
horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed;
if(Input.GetButtonDown("Jump"))
{
jump = true;
}
}
private void FixedUpdate()
{
controller.Move(horizontalMove * Time.fixedDeltaTime, false, jump);
jump = false;
}
}
Maybe the movement on android device is too small to be noticed. Try multiplying speed to delta time and then tweak the speed value to reach your desired movement speed.
rb2d.velocity = new Vector2(direction.x , direction.y) * speed * Time.deltaTime;
Make sure the script is attached to the game object with Rigidbody2D component. Also if your computer doesn't support touch, you can use mouse input to have the same result on computer and mobile device.
if (Input.GetMouseButtonUp(0))
{
rb2d.velocity = Vector2.zero;
}
else if (Input.GetMouseButton(0))
{
touchPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
touchPosition.z = 0;
direction = (touchPosition - transform.position);
rb2d.velocity = new Vector2(direction.x, direction.y) * speed * Time.deltaTime;
}
This code is also works on mobile devices.
Try adding Time.deltaTime or increasing the force with Time.deltaTime.

Unity - problem with arms rotation and flip, body flip and shotting - 2d shooter

I'm starting out with a small shooting game but I have a problem with my character. The arms have to rotate 360º but the body only right or left (depending on where the rotation of the arms by the mouse).
What I got so far is what you see in the video below but I have two big problems and with the help of tutorials.
I was able to rotate and flip my arms but not the body.
Also, when it fires to the right the bullets exit correctly from the firepoint that I created but after the arms flip to the left the bullets (and the weapon fire) are no longer aligned.
Is this approach that I have tried is not the best for this problem?
I appreciate your help.
Game link: https://vimeo.com/310853740
Here my arm rotation script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArmRotation : MonoBehaviour
{
SpriteRenderer spriteRend;
void Awake()
{
spriteRend = GetComponent<SpriteRenderer>();
}
void Update()
{
AimArmAtMouse();
}
void AimArmAtMouse()
{
Vector2 mousePosition = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 armToMouse = mousePosition - (Vector2)transform.position;
float rotationZ = Vector2.SignedAngle(transform.right, armToMouse);
transform.Rotate(0f, 0f, rotationZ);
FlipArm(Vector2.SignedAngle(transform.right, Vector2.right));
}
void FlipArm(float rotation)
{
if (rotation < -90f || rotation > 90f)
{
spriteRend.flipY = true;
}
else
{
spriteRend.flipY = false;
}
}
}
It's because you don't flip the firepoint when you flip the sprite. I re-wrote you script to include a reference to the firepoint. I also added a 'FlipFirePoint' function which gets called by your 'FlipArm' function. It should fix your alignment issue.
using UnityEngine;
public class ArmRotation : MonoBehaviour
{
SpriteRenderer spriteRend;
public Transform firePoint;
void Awake()
{
spriteRend = GetComponent<SpriteRenderer>();
}
void Update()
{
AimArmAtMouse();
}
void AimArmAtMouse()
{
Vector2 mousePosition = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 armToMouse = mousePosition - (Vector2)transform.position;
float rotationZ = Vector2.SignedAngle(transform.right, armToMouse);
transform.Rotate(0f, 0f, rotationZ);
FlipArm(Vector2.SignedAngle(transform.right, Vector2.right));
}
void FlipArm(float rotation)
{
if (rotation < -90f || rotation > 90f)
{
spriteRend.flipY = true;
FlipFirePoint(true);
}
else
{
spriteRend.flipY = false;
FlipFirePoint(false);
}
}
void FlipFirePoint(bool flip)
{
var pos = firePoint.localPosition;
pos.x = Mathf.Abs(pos.x) * (flip ? -1 : 1);
firePoint.localPosition = pos;
}
}
#Sean, I separated the main_body from the arms and made a new script just for body rotation but now it happens to me this:
My test char
The code:
void Update()
{
Flip();
}
void Flip()
{
Vector3 theScale = transform.localScale;
Vector3 pos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
float WorldXPos = Camera.main.ScreenToWorldPoint(pos).x;
if (WorldXPos > gameObject.transform.position.x)
{
theScale.x = 1;
transform.localScale = theScale;
}
else
{
theScale.x = -1;
transform.localScale = theScale;
}
}}
Almost there but not yet i need😁

How to move yoke in the vertical axis

I am trying to move an airplane yoke in the vertical axis. I am using the mouse pointer to move yoke in vertical axis up and down and clamped the value. When I run the script the yoke is positioned some ever and not moving up and down. The yoke is not moving up and down. How to move yoke up and down as shown in the image using below code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace plane
{
public class IP_AirplaneThrottle_Physical : MonoBehaviour
{
#region Variables
public float maxZOffset = -0.5f;
public float sensitivity = 0.001f;
public float smoothSpeed = 8f;
public bool isHitting = false;
public float wantedDelta;
private Vector3 startPos;
private Vector3 wantedPos;
private Vector2 lastMousePosition;
#endregion
#region Builtin Methods
// Use this for initialization
void Start()
{
//Get the lever starting position
startPos = transform.position;
}
// Update is called once per frame
void Update()
{
HandleRaycast();
HandleInteraction();
}
#endregion
#region Custom Methods
void HandleRaycast()
{
//Build a ray so we can see if we are hitting the lever
Ray curRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
//Do our Raycast into the scene
if(Physics.Raycast(curRay, out hit, 1000f))
{
if(hit.transform.GetInstanceID() == this.transform.GetInstanceID())
{
Debug.Log("Hitting the Lever!");
if(Input.GetMouseButtonDown(0))
{
//We are hitting so get the start mouse position
isHitting = true;
lastMousePosition = Input.mousePosition;
print ("123");
}
}
}
//If we let go of the left mouse button then stop everything
if(isHitting && Input.GetMouseButton(0) == false)
{
isHitting = false;
}
}
void HandleInteraction()
{
if(isHitting)
{
//Calculate the delta for Z offset
wantedDelta = (lastMousePosition.y - Input.mousePosition.y) * Time.deltaTime * sensitivity;
startPos.z += wantedDelta;
//make sure we dont go to far
startPos.z = Mathf.Clamp(startPos.z, maxZOffset, 0f);
wantedPos = startPos;
//Get the New Mouse Position every frame while we are holding
lastMousePosition = Input.mousePosition;
}
else
{
//Clear out the Delta value
wantedDelta = 0f;
}
//Move the lever
transform.position = Vector3.Lerp(transform.position, wantedPos, Time.deltaTime * smoothSpeed);
}
#endregion
}
}