Object spawning itself when other object is close enough - c#

How can I make the water in my game (picture below) clone itself and put the clone right next to itself, when another object (the player) is close enough?
Scene:scene
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Paralax : MonoBehaviour
{
// The player
public Transform player;
// The distance from the player needed to copy itself
public float distanceToSpawn = 30f;
// The object
public Transform trans;
bool alreadySpawned;
private void Update()
{
if(!alreadySpawned)
{
// Getting the distance between
float dst = Mathf.Abs(player.position.x - transform.position.x);
if (dst < distanceToSpawn)
{
Transform newTrans = trans;
newTrans.position = (transform.position - new Vector3(/* negative width of the water so it copies itself to the left*/-15.72f, 0f, 0f));
Instantiate(gameObject, newTrans);
alreadySpawned = true;
}
}
}
}
But for some reason the water I placed in the scene is just getting away from the player, and not copying itself. Can anyone help me?

It sounds like trans was maybe the same as transform and therefore you move this very same object away before you spawn a new clone of it as a child.
You would probably rather simply do
var newObj = Instantiate(gameObject, transform);
newObj.transform.position = transform.position + Vector3.left * 15.72f;

Related

Unity3D FollowCam not following player vehicle

I have a garage that gives the option for the player to select the car he wants to take to the race, the problem is the camera doesn't attach to the when it's sent.
The follow camera is using the standard unity assets.
Garage code(This code loads the car into the map):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class LoadCharacter : MonoBehaviour
{
public GameObject[] characterPrefabs;
public Transform spawnPoint;
//public TMP_Text label;
void Start()
{
int selectedCharacter = PlayerPrefs.GetInt("selectedCharacter");
GameObject prefab = characterPrefabs[selectedCharacter];
GameObject clone = Instantiate(prefab, spawnPoint.position, Quaternion.identity);
//label.text = prefab.name;
}
}
Camera code:
using System;
using UnityEngine;
#if UNITY_EDITOR
#endif
namespace UnityStandardAssets.Cameras
{
[ExecuteInEditMode]
public class AutoCam : PivotBasedCameraRig
{
[SerializeField] private float m_MoveSpeed = 3; // How fast the rig will move to keep up with target's position
[SerializeField] private float m_TurnSpeed = 1; // How fast the rig will turn to keep up with target's rotation
[SerializeField] private float m_RollSpeed = 0.2f;// How fast the rig will roll (around Z axis) to match target's roll.
[SerializeField] private bool m_FollowVelocity = false;// Whether the rig will rotate in the direction of the target's velocity.
[SerializeField] private bool m_FollowTilt = true; // Whether the rig will tilt (around X axis) with the target.
[SerializeField] private float m_SpinTurnLimit = 90;// The threshold beyond which the camera stops following the target's rotation. (used in situations where a car spins out, for example)
[SerializeField] private float m_TargetVelocityLowerLimit = 4f;// the minimum velocity above which the camera turns towards the object's velocity. Below this we use the object's forward direction.
[SerializeField] private float m_SmoothTurnTime = 0.2f; // the smoothing for the camera's rotation
private float m_LastFlatAngle; // The relative angle of the target and the rig from the previous frame.
private float m_CurrentTurnAmount; // How much to turn the camera
private float m_TurnSpeedVelocityChange; // The change in the turn speed velocity
private Vector3 m_RollUp = Vector3.up;// The roll of the camera around the z axis ( generally this will always just be up )
protected override void FollowTarget(float deltaTime)
{
// if no target, or no time passed then we quit early, as there is nothing to do
if (!(deltaTime > 0) || m_Target == null)
{
return;
}
// initialise some vars, we'll be modifying these in a moment
var targetForward = m_Target.forward;
var targetUp = m_Target.up;
if (m_FollowVelocity && Application.isPlaying)
{
// in follow velocity mode, the camera's rotation is aligned towards the object's velocity direction
// but only if the object is traveling faster than a given threshold.
if (targetRigidbody.velocity.magnitude > m_TargetVelocityLowerLimit)
{
// velocity is high enough, so we'll use the target's velocty
targetForward = targetRigidbody.velocity.normalized;
targetUp = Vector3.up;
}
else
{
targetUp = Vector3.up;
}
m_CurrentTurnAmount = Mathf.SmoothDamp(m_CurrentTurnAmount, 1, ref m_TurnSpeedVelocityChange, m_SmoothTurnTime);
}
else
{
// we're in 'follow rotation' mode, where the camera rig's rotation follows the object's rotation.
// This section allows the camera to stop following the target's rotation when the target is spinning too fast.
// eg when a car has been knocked into a spin. The camera will resume following the rotation
// of the target when the target's angular velocity slows below the threshold.
var currentFlatAngle = Mathf.Atan2(targetForward.x, targetForward.z)*Mathf.Rad2Deg;
if (m_SpinTurnLimit > 0)
{
var targetSpinSpeed = Mathf.Abs(Mathf.DeltaAngle(m_LastFlatAngle, currentFlatAngle))/deltaTime;
var desiredTurnAmount = Mathf.InverseLerp(m_SpinTurnLimit, m_SpinTurnLimit*0.75f, targetSpinSpeed);
var turnReactSpeed = (m_CurrentTurnAmount > desiredTurnAmount ? .1f : 1f);
if (Application.isPlaying)
{
m_CurrentTurnAmount = Mathf.SmoothDamp(m_CurrentTurnAmount, desiredTurnAmount,
ref m_TurnSpeedVelocityChange, turnReactSpeed);
}
else
{
// for editor mode, smoothdamp won't work because it uses deltaTime internally
m_CurrentTurnAmount = desiredTurnAmount;
}
}
else
{
m_CurrentTurnAmount = 1;
}
m_LastFlatAngle = currentFlatAngle;
}
// camera position moves towards target position:
transform.position = Vector3.Lerp(transform.position, m_Target.position, deltaTime*m_MoveSpeed);
// camera's rotation is split into two parts, which can have independend speed settings:
// rotating towards the target's forward direction (which encompasses its 'yaw' and 'pitch')
if (!m_FollowTilt)
{
targetForward.y = 0;
if (targetForward.sqrMagnitude < float.Epsilon)
{
targetForward = transform.forward;
}
}
var rollRotation = Quaternion.LookRotation(targetForward, m_RollUp);
// and aligning with the target object's up direction (i.e. its 'roll')
m_RollUp = m_RollSpeed > 0 ? Vector3.Slerp(m_RollUp, targetUp, m_RollSpeed*deltaTime) : Vector3.up;
transform.rotation = Quaternion.Lerp(transform.rotation, rollRotation, m_TurnSpeed*m_CurrentTurnAmount*deltaTime);
}
}
}
This are the cars that the map gets from the selection
This is the follow cam
This is what happens when the player chooses the car, it switches places with an empty object
The only way to follow is if I go in the editor and manually drag the car into the follow
Edit: I found a way to work around it, anyone wondering you just have to make a prefab with the car and camera.

Moving Maincamera slowly to another position

I want to move main camera slowly from one point to another point when a button is pressed. This button calls the method which has the code to move the camera.
I have tried using the Lerp method but the camera position is changing so fast that when I click on the button camera directly shifting to a new position. I want the camera to move slowly to a new position.
Below is my code, can anyone please help me with this.
=========================================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cameramove : MonoBehaviour
{
public GameObject cam;
Vector3 moveToPosition;// This is where the camera will move after the start
float speed = 2f; // this is the speed at which the camera moves
public void move()
{
//Assigning new position to moveTOPosition
moveToPosition = new Vector3(200f, 400f, -220f);
float step = speed * Time.deltaTime;
cam.transform.position = Vector3.Lerp(cam.transform.position, moveToPosition, step);
cam.transform.position = moveToPosition;
}
}
It's easier to use lerp with frames and you need to use it in an Update function. Try using the example from the Unity docs:
public int interpolationFramesCount = 45; // Number of frames to completely interpolate between the 2 positions
int elapsedFrames = 0;
void Update()
{
float interpolationRatio = (float)elapsedFrames / interpolationFramesCount;
Vector3 interpolatedPosition = Vector3.Lerp(Vector3.up, Vector3.forward, interpolationRatio);
elapsedFrames = (elapsedFrames + 1) % (interpolationFramesCount + 1); // reset elapsedFrames to zero after it reached (interpolationFramesCount + 1)
Debug.DrawLine(Vector3.zero, Vector3.up, Color.green);
Debug.DrawLine(Vector3.zero, Vector3.forward, Color.blue);
Debug.DrawLine(Vector3.zero, interpolatedPosition, Color.yellow);
}
Try using smooth damp.
Here is the new code you should try:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cameramove : MonoBehaviour
{
Vector3 matric;
public GameObject cam;
Vector3 moveToPosition;
float speed = 2f;
bool move_ = false;
void Update(){
if(move_){
//Assigning new position to moveTOPosition
moveToPosition = new Vector3(200f, 400f, -220f);
cam.transform.position =
Vector3.SmoothDamp(cam.transform.position,
moveToPosition,
ref matric, speed);
}
}
public void move()
{
move_ = true;
}
}

How do I detect if a sprite is overlapping any background sprite?

I want to detect if an empty gameobject is between a sprite which I've drawn and the camera.
Background objects are tagged "Background" and are in the layer "background".
Currently, the Debug.log statement always says "Does not detect background". I've tried switching the direction of the raycast from back to forward several times and that didn't fix it. The gameobject shooting the ray has a z position of -1, the sprite has a z position of 0. The sprite has a 2D box collider on it.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoomMaker : MonoBehaviour
{
public float speed = 5;
public float distance = 5;
public Transform horse;
public Transform carriage;
void Update()
{
transform.Translate(Vector2.right * speed * Time.deltaTime);
RaycastHit2D backgroundInfo = Physics2D.Raycast(horse.position, Vector3.forward, distance);
if (backgroundInfo)
{
Debug.Log("DETECTSBACKGROUND");
}
else
{
Debug.Log("Does not detect Background");
//it always displays this one, it never displays the other debug.log
}
}
}
Consider using Physics2D.OverlapPointAll instead of a raycast.
This will require that background sprites have Collider2D components on their gameobjects, their gameobjects be tagged Background and be on the background layer.
I advise having the background layer ignore collisions with everything. See the physics 2d options documentation for more information on how to do that.
Here's what the code could look like:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoomMaker : MonoBehaviour
{
public float speed = 5;
public float distance = 5;
public Transform horse;
public Transform carriage;
void FixedUpdate() // otherwise, visual lag can make for inconsistent collision checking.
{
transform.Translate(Vector2.right * speed * Time.deltaTime);
Collider2D[] cols = Physics2D.OverlapPointAll(
Vector3.Scale(new Vector3(1,1,0), horse.position), // background at z=0
LayerMask.GetMask("background")); // ignore non background layer objects
Collider2D backgroundCol = null;
for (int i = 0 ; i < cols.Length ; i++) // order of increasing z value
{
if (cols[i].tag == "Background") // may be redundant with layer mask
{
backgroundCol = cols[i];
break;
}
}
if (backgroundCol != null)
{
Debug.Log("DETECTSBACKGROUND: " + backgroundCol.name);
}
else
{
Debug.Log("Does not detect Background");
}
}
}
I tested with this setup:

Unity C# unusual obit

I was making a game about space, like KSP and other space simulator game.
This is the normal orbit.
The normal orbit is a circle.
But this is my orbit .
I try using Collider2D and Point effector2D to create gravity but it is not well too.
This is my code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Gravity : MonoBehaviour {
public float Mass;
private List<GameObject> InRangeObjects;
// Use this for initialization
void Start () {
InRangeObjects = new List<GameObject>();
}
// Update is called once per frame
void Update () {
ApplyGravity();
}
void OnTriggerStay2D(Collider2D col)
{
List<GameObject> InRangeObjectstemp = new List<GameObject>();
InRangeObjectstemp.Add(col.gameObject);
InRangeObjects = InRangeObjectstemp;
////////////////////////////////////
}
public void ApplyGravity()
{
foreach (GameObject Ga in InRangeObjects)
{
float distance = (Ga.transform.position - transform.position).magnitude;
if (Ga.GetComponent<TotalDataStorer>().UseInGameGravity == true)
{
float GravitationalPule = (6.673e-11f * ((Mass * Ga.GetComponent<Rigidbody2D>().mass) / (distance * distance))) * Time.deltaTime;
Debug.Log(GravitationalPule);
Vector3 temp = Ga.transform.position - transform.position;
Ga.GetComponent<Rigidbody2D>().AddForce(new Vector2(temp.x, temp.y) * GravitationalPule * -1) ;
}
}
}
}
I have a flower like orbit, how can I fix this?
The problem is your object is not traveling fast enough, that is an orbit of a slow moving outer object not a regular "circular" orbit, you will have to tweak the speed at which your object is moving. In general you got everything right, it is an orbit, and it is mathematically correct, just you need to get the initial conditions correct.
Oh and you spelled pull wrong in GravitationalPule, it is GravitationalPull.

Unity 3D How to setup Turret Auto Aim? C#

what i't trying to achieve is have my turrent rotate and follow an "Enemy".
At the moment it detects the enemy but it is not rotating and I don't know why.
The bullet it a prefab i drag in, there has to be a better way to do this? Anyone have any suggestions please?
At the moment the bullet never triggers, but the log Shoot and does...and the rotate doesn't work.
Here is what i have
using UnityEngine;
using System.Collections;
public class TurretController : MonoBehaviour {
public Rigidbody bulletPrefab;
private Transform target;
private GameObject bullet;
private float nextFire;
private Quaternion targetPos;
void OnTriggerEnter(Collider otherCollider) {
if (otherCollider.CompareTag("Enemy"))
{
Debug.Log ("in");
target = otherCollider.transform;
StartCoroutine ("Fire");
}
}
void OnTriggerExit(Collider otherCollider) {
if (otherCollider.CompareTag("Enemy"))
{
Debug.Log ("out");
target = null;
StopCoroutine("Fire"); // aborts the currently running Fire() coroutine
}
}
IEnumerator Fire()
{
while (target != null)
{
nextFire = Time.time + 0.5f;
while (Time.time < nextFire)
{
// smooth the moving of the turret
targetPos = Quaternion.LookRotation (target.position);
transform.rotation = Quaternion.Slerp(transform.rotation, targetPos, Time.deltaTime * 5);
yield return new WaitForEndOfFrame();
}
// fire!
Debug.Log ("shoot");
bullet = Instantiate(bulletPrefab, transform.position, transform.rotation) as GameObject;
//bullet.rigidbody.velocity = transform.forward * bulletSpeed;
}
}
}
I tried to change the instantiate part by using this instead
bullet = (GameObject)Instantiate(bulletPrefab, transform.position, transform.rotation);
bullet.GetComponent<Bullet>().target = target.transform;
But then i just get errors like "InvalidCastException: Cannot cast from source type to destination type.
TurretController+c__Iterator0.MoveNext () (at Assets/Scripts/TurretController.cs:44)"
BTW, here's the turret rotation code I used in my project (shared with permission):
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Turret : MonoBehaviour
{
[SerializeField]
private float turnRateRadians = 2 * Mathf.PI;
[SerializeField]
private Transform turretTop; // the gun part that rotates
[SerializeField]
private Transform bulletSpawnPoint;
private Enemy target;
void Update()
{
TargetEnemy();
}
void TargetEnemy()
{
if (target == null || target.health <= 0)
target = Enemy.GetClosestEnemy(turretTop, filter: enemy => enemy.health > 0);
if (target != null)
{
Vector3 targetDir = target.transform.position - transform.position;
// Rotating in 2D Plane...
targetDir.y = 0.0f;
targetDir = targetDir.normalized;
Vector3 currentDir = turretTop.forward;
currentDir = Vector3.RotateTowards(currentDir, targetDir, turnRateRadians*Time.deltaTime, 1.0f);
Quaternion qDir = new Quaternion();
qDir.SetLookRotation(currentDir, Vector3.up);
turretTop.rotation = qDir;
}
}
}
class Enemy : MonoBehaviour
{
public float health = 0;
private static HashSet<Enemy> allEnemies = new HashSet<Enemy>();
void Awake()
{
allEnemies.Add(this);
}
void OnDestroy()
{
allEnemies.Remove(this);
}
/// <summary>
/// Get the closest enemy to some transform, optionally filtering
/// (for example, enemies that aren't dead, or enemies of a certain type).
/// </summary>
public static Enemy GetClosestEnemy(Transform referenceTransform, System.Predicate<Enemy> filter=null)
{
// Left as an exercise for the reader.
// Remember not to use Vector3.Distance in a loop if you don't need it. ;-)
// return allEnemies[0];
}
}
First problem: the bullet prefab. The variable type is RigidBody. If you want to treat it as a game object, the variable must be a game object. Or you can instantiate it, cast to RigidBody, then use the .gameObject accessor. Like this:
((RigidBody)Instantiate(theRigidbody)).gameObject
Second problem: start simple with the rotation. If it's not working, don't get fancy yet. Start with something like this (an instant rotation toward the target):
Vector3 targetDirection = target.transform.position - transform.position;
targetDirection.y = 0; // optional: don't look up
transform.forward = targetDirection;
If it works, then add small pieces of additional complexity until it does exactly what you want. And if you don't get things figured out, give me a shout (a comment) on Monday. I've written turret-aiming code (including a maximum rotation speed), and I don't think my boss would mind if I upload it.

Categories