How to apply render texture(as target texture) on instantiated camera? - c#

I have a camera prefab which I instantiate 4 times in different locations where I want to add render texture(as target texture) on it so I could take the same texture and apply on a plane for monitoring in one of the scene. Please ask if it is not clear. I am trying to make a surveillance monitoring but do not know how to do this and I am stuck at this. please give examples Thanks in advance.

I think the unity manual explains it very well https://docs.unity3d.com/Manual/class-RenderTexture.html.
To be a bit more specific, here's a possible implementation:
Create some RenderTextures in the AssetFolder, than you have to link them to your Camera script to get them rendered. Add this file to your TextureRender-Camera.
using System.Collections;
using UnityEngine;
public class Camera2Texture : MonoBehaviour {
public RenderTexture[] renderTextures;
private Camera cam;
private void Awake()
{
cam = GetComponent<Camera>();
}
private void Start()
{
StartCoroutine(RenderTexturesCoroutine());
}
IEnumerator RenderTexturesCoroutine()
{
for (int i = 0; i < renderTextures.Length; i++)
{
// just move the camera a little bit and focus the center of the scene
this.transform.position += Vector3.left * 2 * i;
cam.transform.LookAt(Vector3.zero);
cam.targetTexture = renderTextures[i];
yield return new WaitForSeconds(1f);
cam.Render();
}
cam.targetTexture = null;
this.gameObject.SetActive(false);
}
}
I start a coroutine which moves my TextureRender-Camera a little bit every second, put in the next RenderTexture from the array and render the image. At the end I disable the Camera. And this is the result when you put all 4 RenderTextures on Quads: Result

Related

I control the gameobject by tilting the phone and need to keep it balanced in whatever the rotation of the phone is when game starts

I published a game named Rotate Ball Pro last week. But some people told me that playing the game was not so comfortable.
I used unity and C# for coding. My game levels has labyrinths and a sphere on it. The sphere has rigidbody component but the labyrinths have not. So you can control the labyrinth by tilting the phone and thus the sphere can roll. But you must hold the phone parallel to the ground to keep the labyrinth balanced. For example you can not play by lying on back or holding the phone with any angle. So this makes playing uncomfortable.
I want to to keep the labyrinth balanced in whatever the rotation of the phone is when the game starts. I searched web and tried many things but could not solve it. Can anyone help me?
Here is the explanation of the problem with an image: Problem
Here is the direct game link: Rotate Ball Pro
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class NewMovementScript : MonoBehaviour
{
public float multiplier = 0;
void Start()
{
Input.gyro.enabled = true;
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
void FixedUpdate()
{
var dir = Vector3.zero;
dir.x = Input.acceleration.x * -1 * multiplier;
dir.y = Input.acceleration.z * multiplier;
dir.z = Input.acceleration.y * multiplier;
transform.eulerAngles = new Vector3(dir.z, 0f, dir.x);
}
}
Input.acceleration is the position change between the last and current frame and as you noted already doesn't take the initial state into account.
This also is barely related to rotations at all.
I think for your usage you would rather simply use Input.gyro.attitude!
Example from the docs
public class Example : MonoBehaviour
{
// Rotate the object to match the device's orientation
// in space.
void Update()
{
transform.rotation = Input.gyro.attitude;
}
}
If your object uses a rigidbody you might want to rather use
public class Example : MonoBehaviour
{
private Rigidbody rigidbody;
void Awake ()
{
rigidbody = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
rigidbody.MoveRotation(Input.gyro.attitude);
}
}

Unity c# - unable to Spawn Prefabs on a NavMesh

I am trying to make a zombie wave game and current have a Prefab for my enemies. If I have the prefab be in the scene when I hit run, they are attached to the NavMesh and track the player perfectly. I want to achieve this but with the enemy being spawned from an empty GameObject so I can get the waves spawning in. I have achieved them Spawning but they have the error,
"SetDestination" can only be called on an active agent that has been placed on a NavMesh.
UnityEngine.AI.NavMeshAgent:SetDestination(Vector3)
EnemyAI:Update() (at Assets/Scripts/EnemyAI.cs:25)
Here is my EnemyAI Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class EnemyAI : MonoBehaviour
{
public float lookRadius = 10f;
Transform target;
NavMeshAgent agent;
public GameObject Player;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
float distance = Vector3.Distance(Player.transform.position, transform.position);
if (distance <= lookRadius)
{
agent.SetDestination(Player.transform.position);
}
}
}
And my spawning script, which is attached to an empty game object,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawning : MonoBehaviour
{
public GameObject prefab;
public int CountofCubes;
private IEnumerator coroutine;
public float spawnRate;
IEnumerator Start()
{
while (true)
{
for (int i = 0; i < CountofCubes; i++)
{
Instantiate(prefab, new Vector3(Random.Range(-25.0f, 25.0f), 0.5f, Random.Range(-25.0f, 25.0f)), Quaternion.identity);
}
yield return new WaitForSeconds(spawnRate);
}
}
}
Any help would be great thanks!
I had the same issue and I don't have an explanation but only a workaround:
In the Start fucntion, I added:
navAgent = GetComponent<NavMeshAgent>();
navAgent.enabled = false;
// Invoke is used as a workaround for enabling NavMeshAgent on NavMeshSurface
Invoke("EnableNavMeshAgent", 0.025f);
And the EnableNavMeshAgent function is just :
private void EnableNavMeshAgent ()
{
navAgent.enabled = true;
}
If I set the invoke delay to a value less than 0.025 second the error keep going but for 0.025 I only have it twice and the behaviour is the one I wanted after that.
Some reasons this might happen:
The agent is not on level with any navmesh i.e. can be too far above or below. You want it to be "close to the NavMesh surface". Use raycasting on the floor to position the agent or add a rigidbody and drop it from above the floor. After you do this you might need to disable and enable the agent.
Moving the transform yourself rather than using Wrap function. There's property where you can check if the simulated and actual position are in sync.
Corrupted navmesh so you might need to re-bake it.
It is essentially trying to tell you your agent is not on the mesh so it cannot find a path. Try playing with where you're placing the agent.
I kind of remember running into a similar problem a while back and problem was I forgot to bake the NavMesh in Window > AI > Navigation. Just in case.

Particle system rendering behind another GameObject

First, I want you to understand my English.
I manually change the camera's projection to orthographic using the source code.
Please refer to the code below.
using UnityEngine;
using System.Collections;
public class CameraOrthoController : MonoBehaviour
{
private Matrix4x4 ortho;
private Matrix4x4 perspective;
public float near = 0.001f;
public float far = 1000f;
private float aspect;
public static CameraOrthoController Instance
{
get
{
return instance;
}
set { }
}
//-----------------------------------------------------
private static CameraOrthoController instance = null;
//---------------------------------------------------
// Use this for initialization
void Awake()
{
if (instance)
{
DestroyImmediate(gameObject);
return;
}
// 이 인스턴스를 유효한 유일 오브젝트로 만든다
instance = this;
}
private void Start()
{
perspective = Camera.main.projectionMatrix;
}
public void StartMatrixBlender(float OrthoSize)
{
aspect = (Screen.width + 0.0f) / (Screen.height + 0.0f);
if (OrthoSize != 0f)
{
float vertical = OrthoSize;
float horizontal = (vertical * 16f) / 9f;
ortho = Matrix4x4.Ortho(-horizontal, horizontal, -vertical, vertical, near, far);
BlendToMatrix(ortho, 1f);
}
else
{
BlendToMatrix(perspective, 1f);
}
}
//---------------------------------------
private Matrix4x4 MatrixLerp(Matrix4x4 from, Matrix4x4 to, float time)
{
Matrix4x4 ret = new Matrix4x4();
int i;
for (i = 0; i < 16; i++)
ret[i] = Mathf.Lerp(from[i], to[i], time);
return ret;
}
IEnumerator LerpFromTo(Matrix4x4 src, Matrix4x4 dest, float duration)
{
float startTime = Time.time;
while (Time.time - startTime < duration)
{
Camera.main.projectionMatrix = MatrixLerp(src, dest, (Time.time - startTime) / duration);
yield return new WaitForSeconds(0f);
}
Camera.main.projectionMatrix = dest;
}
//-------------------------------------------------
private Coroutine BlendToMatrix(Matrix4x4 targetMatrix, float duration)
{
StopAllCoroutines();
return StartCoroutine(LerpFromTo(Camera.main.projectionMatrix, targetMatrix, duration));
}
//-------------------------------------------------
public void OnEvent(EVENT_TYPE Event_Type, Component Sender, object Param = null, object Param2 = null)
{
switch (Event_Type)
{
}
}
}
I use code this way.
CameraOrthoController.Instance.StartMatrixBlender(OrthographicSize);
This has worked well so far.
However, the problem occurred when i added particle system for effect.
The screen where the problem is occurring
In a normal state, the effect appears in front of the gameobject, as shown on the scene screen at the bottom of the picture above.
But if I use the code I wrote above to manipulate the camera, the effect will always be obscured by all gameobject, as if it were on the game screen at the top of the picture. Despite the fact that the effects are located in front of the game object.
At first, I thought it would be possible to solve it with layer sorting, but I don't think it's a layer problem because it's visible under normal camera conditions.
I want to know where the problem is with the above codes because I have to use them.
Please let me know if you know how to solve it.
Thank you.
When you modify Camera.projectionMatrix, the camera will no longer update its rendering based on the field of view. The particle will remain behind the GameObject until you call Camera.ResetProjectionMatrix() which ends the effect off setting the Camera.projectionMatrix property.
If this doesn't work, use multiple cameras to make the particle system always appear on top of the 3D object. Basically, you render the 3D Object and other objects with the main camera then render the Particle System with another camera.
Layer:
1.Create new layer and name it "Particle"
2.Change the Particle System layer to Particle
Main Camera:
1.Make sure that the main camera's Clear Flags is set to Skybox.
2.Change the Culling Mask to "Everything". Click on Everything which is a setting of Culling Mask and de-select/uncheck Particle.
3.Make sure that its Depth is set to 0.
The camera should not render the Particle System at this point.
New Camera:
1.Create new Camera. Make sure it's at the-same position/rotation as the main camera. Also remove the AudioListener that is attached to it.
2.Change Clear Flags to Depth only.
3.Change the Culling Mask of the camera to be Particle and make sure that nothing else is selected in the "Culling Mask"
4.Change Depth to 1.
This will make the Particle System to always display on top of every object rendered with the first or main camera.
If you want the Particle System to appear on top of a Sprite/2d Object instead of Mesh/3D Object, change the sortingOrder of the particle's Renderer to be bigger than the SpriteRenderer's sortingOrder. The default is 0 so changing the Particle's sortingOrder to 1 or 2 should be fine.
particle.GetComponent<Renderer>().sortingOrder = 2;

making a 2D GameObject react to the position of another 2D GameObject

So, my boss moves in a specific direction when it detects the player. The problem I'm having is how to get the boss to move depending on where the player is within a certain proximity. So if the boss is on the player's left, he'll move to the left. If he's on the player's right, he'll move to the right. But I can't figure out how to make him react based on distance. Right now I'm just doing a Debug.Log to save a few seconds.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class phantom : MonoBehaviour {
private Rigidbody2D rb;
private Animator anim;
public Transform Target;
void Start ()
{
rb = GetComponent<Rigidbody2D> ();
anim = GetComponent<Animator> ();
}
void Update ()
{
if (transform.position.x > Target.position.x ) {
Debug.Log ("left");
}
if (transform.position.x < Target.position.x ) {
Debug.Log ("right");
}
}
}
You could use the Vector3.Distance method to determine the distance between your two object based on thier respective transform. That way, you can modify your boss's behavior according to his proximity to the player. The smaller the magnitude value is, the closer your two transforms are.
Ex:
int distanceYouWant;
if(Vector3.Distance(transform.position, Target.position).magnitude < distanceToDoStuff)
{
Debug.Log("Boss do stuff!");
}
Here is the link to the Unity scripting API doc: https://docs.unity3d.com/ScriptReference/Vector3.Distance.html
Hope this helps!
I figured it out. I just made the function not in Update but with an OnTriggerEnterStay2d (Collider2D other). Then I placed a trigger collider on the same GameObject and only when it detects the Target (the player) does the debug come up.

How to attach the camera to a player object instantiated by HLAPI Network Manager?

In short, I have a very simple multiplayer game. It's the Roll A Ball game (Unity3D tutorial). So right now I have the players etc spawning perfectly and everyone is able to control their own balls perfectly fine.
But here's the problem: I've got a default Main Camera. Since it's only the local player itself that needs to see it, I figured there's no point in trying to spawn a seperate camera for each player on the server.
However, to make the camera follow the player, I need to attach it the player gameobject. Obviously I can't attach it to the player prefab as it's a clone the camera needs to follow. But since the player is being spawned by the Network Manager component, I have no idea on how to refer to this clone.
What I've tried myself:
public class CameraController : NetworkManager
{
public GameObject playerPrefab;
public Transform target;
private Vector3 offset;
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
{
GameObject player = (GameObject)Instantiate(playerPrefab, new Vector3(0, 0.5f, 0), Quaternion.identity);
target = player.transform;
NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
}
void Start()
{
offset = transform.position - target.position;
}
void LateUpdate()
{
transform.position = transform.position + offset;
}
}
But this resulted in:
Which I find extremely odd since as you can clearly see, there's no NetworkIdentity component on the NetworkManager object. I've been trying A LOT of things for the past 4 hours now and I just can't do it. So now I'm hoping you guys can help me out.
Edit: This is how the Network Manager normally spawns a player. As you can see, there's no code for it:
I had the same issue and figured out the followig solution. Seems like you already got a solution, but maybe it is interesting to share some possible ways for other people in the same situation.
This is a way to do it without a camera attached to the prefabs.
I'm using a NetworkManager to instantiate Player-prefabs. (Same as you)
I solved the problem of finding references to the clone objects by letting the clones tell the camera, who they are (or which transform belongs to them).
The Player has the following script:
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public class PlayerController : NetworkBehaviour {
public override void OnStartLocalPlayer()
{
GetComponent<MeshRenderer>().material.color = Color.blue;
Camera.main.GetComponent<CameraFollow>().target=transform; //Fix camera on "me"
}
void Update ()
{
if (!isLocalPlayer)
{
return;
}
var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
var z = Input.GetAxis ("Vertical") * Time.deltaTime * 3.0f;
transform.Rotate (0, x, 0);
transform.Translate (0,0,z);
}
}
On my default main Camera (there is no camera attached to the player prefab, just the default camera) I put the following script on. It takes a target which I initialised with the prefab using the inspector.
using UnityEngine;
using System.Collections;
public class CameraFollow : MonoBehaviour {
public Transform target; //what to follow
public float smoothing = 5f; //camera speed
Vector3 offset;
void Start()
{
offset = transform.position - target.position;
}
void FixedUpdate()
{
Vector3 targetCamPos = target.position + offset;
transform.position = Vector3.Lerp (transform.position, targetCamPos,smoothing * Time.deltaTime);
}
}
After starting the game, each clone tells the camera who he is, so the target changes to the individual clients clone with this line from the Player's Script:
Camera.main.GetComponent<CameraFollow>().target=transform; //Fix camera on "me"
This way you don't need to create one camera per instance of player-prefabs (I'm not sure if this makes big differences in performance) and you don't have to deactivate all cameras which don't belong to your client.
If you host the game in the editor you can see that there is just 1 camera instead of one camera per connected client (like when you attach it to the prefab).
I think this is a good use of this method, you can use it to put things in it, which should be applied to the Local Player only.
public override void OnStartLocalPlayer()
{
}
I tried by starting the game in the editor and in a build and it seems to work well.
I would add a camera to the prefab and then write a player script like this:
using UnityEngine.Networking;
public class Player : NetworkBehaviour
{
public Camera camera;
void Awake()
{
if(!isLocalPlayer)
{
camera.enabled = false;
}
}
}
I've not really worked with networking but what if you do this after you spawn the local player
Camera.main.transfor.SetParent(the transform of the local player here);
As I understand the problem each separate instance of the game has a main camera.
Thanks to Rafiwui's point into the right direction, I've finally managed to get it working. All I had to do was adept his code a bit. The end result was:
public Camera camera;
void Awake()
{
camera.enabled = false;
}
public override void OnStartLocalPlayer()
{
camera.enabled = true;
}
Thanks A LOT to you all for helping me out! This has been quite a day for me.

Categories

Resources