I am new to unity and i am trying to create a new game.
using UnityEngine;
using System.Collections;
public class Enemyblue1script : MonoBehaviour {
// Use this for initialization
public float speed; // speed variable
public float RotSpeed = 90f;
public GameObject RocketGO; // Reference to our main character Rocket
void Start ()
{}
void Update()
{
Vector2 Pos = new Vector2 (-10, 5);
gameObject.transform.position = Vector3.MoveTowards (gameObject.transform.position, Pos, speed * Time.deltaTime);
Invoke ("MoveFace", 2f);
}
void MoveFace()
{
if( RocketGO == null)
{
GameObject go = GameObject.FindGameObjectWithTag("Rocket");
if(go != null){
RocketGO = go ;}
}
if( RocketGO == null)
return;
Vector3 dir = RocketGO.transform.position - gameObject.transform.position;
dir.Normalize();
float zAngle = Mathf.Atan2(dir.x , dir.y) * Mathf.Rad2Deg + 360;
Quaternion desiredRot = Quaternion.Euler(0 ,0,-zAngle);
gameObject.transform.rotation = Quaternion.RotateTowards(gameObject.transform.rotation , desiredRot , RotSpeed * Time.deltaTime);
}
}
This is my script for Moving Enemy towards some point (using MoveTowards funtion) and rotating enemy to Players direction. And i have one more script that is for Spawning these enemeies (Two Enemies at a time ) Script is
using UnityEngine;
using System.Collections;
public class Enemy1Spawner : MonoBehaviour {
//our meteorite prefab
public GameObject Enemy1blue;
public float speed;
public GameObject p1;
public GameObject p2;
// Use this for initialization
void Start ()
{}
// Update is called once per frame
void Update ()
{}
void SpawnEnemy1blue()
{
//bottom left point of screen
//Vector2 min = Camera.main.ViewportToWorldPoint (new Vector2 (0, 0));
//top right point of screen
//Vector2 max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1));
GameObject Enemy1ablue = (GameObject)Instantiate (Enemy1blue);
GameObject Enemy2ablue = (GameObject)Instantiate (Enemy1blue);
Enemy1ablue.transform.position = new Vector2 (-11,9);
Enemy2ablue.transform.position = new Vector2 (11,9);
}
public void startEnemy1blueSpawner()
{
Debug.Log ("Invoked Spawning Blue Enemy");
InvokeRepeating ("SpawnEnemy1blue",5f,30f);
}
//function to stop spawning when game over
public void StopEnemy1blueSpawning()
{
CancelInvoke ("SpawnEnemy1blue");
}
}
So now while Spawning enemies! my enemies are moving towards only one point i.e Vector2 Pos = new Vector2 (-10, 5); which I have defined in Updat() method of Enemyblue1script, and i want to spawn two enemies at a different positions one at Vector2 Pos = new Vector2 (-10, 5) (to the left side); and one at Vector2 Pos = new Vector2 (10, 5) (to the right side);
By using these two scripts i am able to spawn two enemies at a time, but they both move to same point, which is what i do not want to happen. I have tried stuff like in ENEMY1SPAWNER script > SpawnEnemy1blue() function i have also created two points using vector2 and i called two Movetowards functions there for two different enemies but is not working they are not moving.
Vector2 Pos1 = new Vector2 (-10, 5);
Vector2 Pos2 = new Vector2 (10, 5);
GameObject Enemy1ablue = (GameObject)Instantiate (Enemy1blue);
GameObject Enemy2ablue = (GameObject)Instantiate (Enemy1blue);
Enemy1ablue.transform.position = new Vector2 (-11,9);
Enemy2ablue.transform.position = new Vector2 (11,9);
Enemy1ablue.transform.position = Vector3.MoveTowards (Enemy1ablue.transform.position, Pos1, speed * Time.deltaTime);
Enemy2ablue.transform.position = Vector3.MoveTowards (Enemy2ablue.transform.position, Pos2, speed * Time.deltaTime);
It's hard to tell exactly where you put this line:
Enemy1ablue.transform.position = Vector3.MoveTowards(
Enemy1ablue.transform.position, Pos1, speed * Time.deltaTime);
But if it's just in SpawnEnemy1blue() then it will only happen once, so the enemy will move a little closer to the target then stop.
I suggest organizing the code a little differently: add a Vector2 target field to Enemyblue1script, set it when you initialize a new enemy, and move towards it in Enemyblue1script.Update. Instead of creating and using Pos, use target.
Related
so I'm making a 2D platformer and I would like to spawn enemies on the whole map but not in the camera range.
I have to mention I am using Cinemachine to follow the player.
This is my script for the spawner:
*public class MobSpawner : MonoBehaviour
{
public GameObject Mob;
float randX;
Vector2 whereToSpawn;
public float spawnRate = 2f;
float nextSpawn = 0.0f;
public GameObject Camera;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Time.time > nextSpawn)
{
nextSpawn = Time.time + spawnRate;
randX = Random.Range(-36f, 62);
whereToSpawn = new Vector2(randX, transform.position.y);
Instantiate(Mob, whereToSpawn, Quaternion.identity);
}
}
}*
As you can see I'm taking 2 points and in between them I spawn enemies. As this range would basically be the entire map, the camera will always be in it.
I want enemies to NOT spawn inside the camera yet spawn outside of it. How can I manage to do this?
I'd say the simplest solution would be to just calculate vector distance between the player position and spawning position. Since this is a 2d space and you are spawning them only on one axis it should be fine.
So you could do
float distanceAwayFromCameraView = 5;
// you will need a method, reference or just get the object via tag
var playerPos = GameObject.Find("Player").transform.position;
randX = Random.Range(-36f, 62);
whereToSpawn = new Vector2(randX, transform.position.y);
while ((Vector2.Distance(whereToSpawn, playerPos) < distanceAwayFromCameraView){
randX = Random.Range(-36f, 62);
whereToSpawn = new Vector2(randX, transform.position.y);
}
Instantiate...
I'm not at my pc to test this right now, please let me know if there's errors
I am a freshman design student and they've asked us to create a game on unity3D without much training on it so needless to say I don't know much except for the super basic stuff. I don't know anything about c# and I've been having an issue making a gameobject teleport. I've spent 6 hours searching for a solution online and the only conclusion I got to was that my object is probably having issues teleporting because of the way I am controlling it - something to do with the controller remembering the last position before the teleport and returning to it. I have no idea how to fix it though.
So this is what my scene looks like: I have a sphere as my character, I move it to this other object that has a collider as trigger which then teleports my sphere to a different point (black object) on the terrain. As soon as my object reaches there, it starts sliding back to the point where the teleport happened. I even tried edit > project settings > physics > auto sync transforms as many suggested that and it worked for them.
This is the code by which I control my player:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyPlayer : MonoBehaviour
{
public float speed = 1;
public float spacing = 1;
private Vector3 pos;
// Use this for initialization
void Awake()
{
pos = transform.position;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.W))
pos.x += spacing;
if (Input.GetKeyDown(KeyCode.S))
pos.x -= spacing;
if (Input.GetKeyDown(KeyCode.D))
pos.z -= spacing;
if (Input.GetKeyDown(KeyCode.A))
pos.z += spacing;
transform.position = Vector3.MoveTowards(transform.position, pos, speed * Time.deltaTime);
}
}
and I also have a camera that follows the sphere using this code
using UnityEngine;
using System.Collections;
public class CompleteCameraController : MonoBehaviour {
public GameObject player; //Public variable to store a reference to the player game object
private Vector3 offset; //Private variable to store the offset distance between the player and camera
// Use this for initialization
void Start ()
{
//Calculate and store the offset value by getting the distance between the player's position and camera's position.
offset = transform.position - player.transform.position;
}
// LateUpdate is called after Update each frame
void LateUpdate ()
{
// Set the position of the camera's transform to be the same as the player's, but offset by the calculated offset distance.
transform.position = player.transform.position + offset;
}
}
and I have another code on the camera that makes me be able to look around using my mouse
using UnityEngine;
using System.Collections;
public class FlyCamera : MonoBehaviour
{
/*
Writen by Windexglow 11-13-10. Use it, edit it, steal it I don't care.
Converted to C# 27-02-13 - no credit wanted.
Simple flycam I made, since I couldn't find any others made public.
Made simple to use (drag and drop, done) for regular keyboard layout
wasd : basic movement
shift : Makes camera accelerate
space : Moves camera on X and Z axis only. So camera doesn't gain any height*/
float mainSpeed = 700.0f; //regular speed
float shiftAdd = 950.0f; //multiplied by how long shift is held. Basically running
float maxShift = 2000.0f; //Maximum speed when holdin gshift
float camSens = 0.25f; //How sensitive it with mouse
private Vector3 lastMouse = new Vector3(255, 255, 255); //kind of in the middle of the screen, rather than at the top (play)
private float totalRun = 1.0f;
void Update()
{
lastMouse = Input.mousePosition - lastMouse;
lastMouse = new Vector3(-lastMouse.y * camSens, lastMouse.x * camSens, 0);
lastMouse = new Vector3(transform.eulerAngles.x + lastMouse.x, transform.eulerAngles.y + lastMouse.y, 0);
transform.eulerAngles = lastMouse;
lastMouse = Input.mousePosition;
//Mouse camera angle done.
//Keyboard commands
float f = 0.0f;
Vector3 p = GetBaseInput();
if (Input.GetKey(KeyCode.LeftShift))
{
totalRun += Time.deltaTime;
p = p * totalRun * shiftAdd;
p.x = Mathf.Clamp(p.x, -maxShift, maxShift);
p.y = Mathf.Clamp(p.y, -maxShift, maxShift);
p.z = Mathf.Clamp(p.z, -maxShift, maxShift);
}
else
{
totalRun = Mathf.Clamp(totalRun * 0.5f, 1f, 1000f);
p = p * mainSpeed;
}
p = p * Time.deltaTime;
Vector3 newPosition = transform.position;
if (Input.GetKey(KeyCode.Space))
{ //If player wants to move on X and Z axis only
transform.Translate(p);
newPosition.x = transform.position.x;
newPosition.z = transform.position.z;
transform.position = newPosition;
}
else
{
transform.Translate(p);
}
}
private Vector3 GetBaseInput()
{ //returns the basic values, if it's 0 than it's not active.
Vector3 p_Velocity = new Vector3();
if (Input.GetKey(KeyCode.W))
{
p_Velocity += new Vector3(0, 0, 1);
}
if (Input.GetKey(KeyCode.S))
{
p_Velocity += new Vector3(0, 0, -1);
}
if (Input.GetKey(KeyCode.A))
{
p_Velocity += new Vector3(-1, 0, 0);
}
if (Input.GetKey(KeyCode.D))
{
p_Velocity += new Vector3(1, 0, 0);
}
return p_Velocity;
}
}
Please let me know if there's a specific part of my code that I need to edit to resolve this or alternatively if you have a different code that won't give me this issue, that would make my life so much easier. If I need to edit something or you're sharing a code, please respond with the complete (corrected) code because otherwise I will just be even more confused.
I know this is a super long post and I am sorry but I am really desperate. It's been really hard studying online and basically having to teach myself all of this. This is for a final project so I will really appreciate any help you can throw my way. Thank you for reading and thanks for any help in advance.
EDIT: The teleport code is executing fine because I do teleport to the chosen location, I just end up sliding back to the point which I teleported from.
This is the teleporting code I am using.
using UnityEngine;
using System.Collections;
public class Teleport : MonoBehaviour
{
public GameObject ui;
public GameObject objToTP;
public Transform tpLoc;
void Start()
{
ui.SetActive(false);
}
void OnTriggerStay(Collider other)
{
ui.SetActive(true);
if ((other.gameObject.tag == "Player") && Input.GetKeyDown(KeyCode.E))
{
objToTP.transform.position = tpLoc.transform.position;
}
}
void OnTriggerExit()
{
ui.SetActive(false);
}
}
Ok, so the main reason why your character is drifting back to original position is that the pos variable in the MyPlayer script stays the same after teleporting.
Remedy for that will be changing pos variable from Teleport script after objToTP.transform.position = tpLoc.transform.position;. Something like objToTP.gameobject.GetComponent<MyPlayer>().pos = tpLoc.transform.position;
But make sure that objToTP has component MyPlayer and pos in MyPlayer is public.
Once again: it's a simple way to resolve your problem. In a real project you should create more flexible architecture, but that's a different story.
I believe that you sliding back because you moving player with transform.position = Vector3.MoveTowards in Update().
And you moving it to coordinates that was got from your input
I was looking to keep the 2d sprite within the screen not go over it.I have created a square sprite as my player and dragged and dropped the following script which works for the movement of the player on x and y axis.
public class PlayerMovement : MonoBehaviour
{
private float moveSpeed = 10f;
// Update is called once per frame
void Update()
{
MovePlayer();
}
private void MovePlayer()
{
float horizontalMovement = Input.GetAxis("Horizontal");
float verticalMovement = Input.GetAxis("Vertical");
horizontalMovement = horizontalMovement * Time.deltaTime * moveSpeed;
horizontalMovement += transform.position.x;
verticalMovement = verticalMovement * Time.deltaTime * moveSpeed;
verticalMovement += transform.position.y;
Vector2 movement = new Vector2(horizontalMovement, verticalMovement);
transform.position = movement;
}
}
When I try to clamp the player(square) within the screen problem arises(script given below).I created another script for clamping the sprite.The square is blinking between left lower screen and right top screen.It is trying to move between two ends.It is because I am getting two position(x and y) and giving its position to the square.But I want to make sure the player does not go beyond the screen bounds.
public class ScreenBoundary : MonoBehaviour
{
public GameObject square;
protected Vector3 screenbounds;
// Start is called before the first frame update
void Start()
{
screenbounds = GetScreenBoundary();
}
// Update is called once per frame
void LateUpdate()
{
Vector3 viewPosition = square.transform.position;
viewPosition.x = Mathf.Clamp(viewPosition.x, screenbounds.x, screenbounds.x * -1);
viewPosition.y = Mathf.Clamp(viewPosition.y, screenbounds.y, screenbounds.y * -1);
square.transform.position = viewPosition;
}
private Vector3 GetScreenBoundary()
{
Camera mainCamera = Camera.main;
Vector3 screenVector = new Vector3(Screen.width, Screen.height, mainCamera.transform.position.z);
return mainCamera.ScreenToWorldPoint(screenVector);
}
}
How to use the above two scripts to keep the sprite within the screen bounds?
So i'm having issues with a script I have, what it does is basically rotate the player graphics depending on where the mouse is aiming at. This works fine and as intended but my issue is that when I want to shoot on the opposite direction, that being the Left direction, it shoots the player instead of where it's aiming at.
I've decided to record a small video to show the problem.
https://streamable.com/02zqz
Here's the code to both the rotation and weapon script.
Rotating
public class Rotating : MonoBehaviour
{
public PlayerController player;
public float x;
public Vector3 flipArm;
void Start()
{
x = transform.localScale.x;
flipArm = transform.localScale;
player = GetComponentInParent<PlayerController>();
}
void Update()
{
Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition ) - transform.position;
difference.Normalize();
float rotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, rotZ + 0);
if(difference.x >= 0)
{
transform.rotation = Quaternion.Euler(0f, 0f, rotZ);
player.armRight = true;
}
else
{
transform.rotation = Quaternion.Euler(0f, 0f, rotZ+180);
player.armRight = false;
}
}
}
Weapon
public class Weapon : MonoBehaviour
{
public float shootDelay = 0;
public float damage = 1;
public LayerMask whatToHit;
public Transform firePoint;
public GameObject bullet;
// Start is called before the first frame update
void Start()
{
firePoint = transform.Find("FirePoint");
}
// Update is called once per frame
void Update()
{
shootDelay += Time.deltaTime;
if(shootDelay >= 0.1f)
{
if(Input.GetMouseButton(0))
{
shootDelay = 0;
Shot();
}
}
}
public void Shot()
{
Vector2 mousepos = new Vector2(Camera.main.ScreenToWorldPoint(Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
Vector2 firepointpos = new Vector2(firePoint.position.x, firePoint.position.y);
Instantiate(bullet, firepointpos, transform.rotation);
Debug.DrawLine(firepointpos, (mousepos - firepointpos) * 100, Color.cyan);
}
}
Try this:
transform.rotation = Quaternion.LookRotation ( end - start );
Also don't forget to check where the player is facing because you don't want to shoot from back. Using the above euler angles, one side is 90 and another 270 degrees in y component.
I am trying to make a simple game where I am shooting a projectile when the user touches the screen, I first spawn 8 projectiles (sprites) and when the user touches the screen I would like the top projectile to fly in the touch direction. I was able to do this; However, every time I shoot, the projectile goes in the wrong direction, here is an image which will illustrate the issue.
Obviously the image is still here but the object will continue flying until it goes out of the screen and then gets destroyed.
Here is the code snippet that handles this
GameplayController.cs
if (Input.GetMouseButtonDown(0))
{
Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
position = Camera.main.ScreenToWorldPoint(position);
GameObject target;
target = new GameObject();
target.transform.position = position;
Arrow comp = currentArrows[0].GetComponent<Arrow>();
comp.setTarget(target.transform);
comp.GetComponent<Arrow>().arrowSpeed = 12;
comp.GetComponent<Arrow>().shoot = true;
currentArrows.RemoveAt(0);
Destroy(target);
}
I know I am getting the mouse input here and not the phone touch and that's fine for me, later I will convert it to the touch input.
Arrow.cs
public bool shoot = false;
public float arrowSpeed = 0.0f;
public Vector3 myDir;
public float speed = 30.0f;
private Transform target;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(shoot)
{
transform.position += transform.right * arrowSpeed * Time.deltaTime;
}
}
public void setTarget(Transform targetTransform)
{
this.target = targetTransform;
Vector3 vectorToTarget = target.position - transform.position;
float angle = Mathf.Atan2(vectorToTarget.y, vectorToTarget.x) * Mathf.Rad2Deg;
Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation, q, Time.deltaTime * speed);
}
private void OnBecameInvisible()
{
print("Disappeared");
Destroy(gameObject);
Gameplay.instance.isShooting = false;
}
Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
I think that your problem is that you're getting the screen coordinates by click, not the world coordinates, which is actually two different things. In order to direct your projectile correctly you need to convert your screen coordinates to world like it's done here.
The next thing is how you move the projectile:
transform.position += transform.right * arrowSpeed * Time.deltaTime;
You're moving the projectile to the right and then rotating it somehow. Maybe you should try to move it with Vector3.Lerp, which will be easier and rotate it with Transform.LookAt.