I'm trying to draw to a texture with the mouse. Mouse coords are given to a shader which outputs to a render texture (I've tried both regular RenterTexture and CustomRenderTexture which is affected directly by a material) and it doesn't seem to work.
I can tell from the material that the mouse's input is obtained, but nothing is visible on the rendertexture.
I'm starting to suspect that rendertextures aren't fully working in HDRP?
Hoping someone can point in the direction of what could be the real issue.
I'm on Unity 2019.3.0f3, shaders is HDRP Unlit Graph
This is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DrawWithMouse : MonoBehaviour
{
public Camera _camera;
public CustomRenderTexture _splatmap;
public Material _drawMaterial;
private RaycastHit _hit;
[Range(1, 100)]
public float _brushSize = 1f;
[Range(0, 10)]
public float _brushStrength = 1f;
private readonly float m_GUIsize = 256;
private readonly int m_RenderTexSize = 1024;
void Start()
{
_splatmap = new CustomRenderTexture(m_RenderTexSize, m_RenderTexSize, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear)
{
name = "splatmap_CRT_generated",
initializationColor = Color.black,
initializationSource = CustomRenderTextureInitializationSource.Material,
initializationMaterial = _drawMaterial,
material = _drawMaterial,
doubleBuffered = true,
updateMode = CustomRenderTextureUpdateMode.OnDemand
};
_drawMaterial.SetVector("_DrawColor", Color.red);
_drawMaterial.SetTexture("_SplatMap", _splatmap);
}
void Update()
{
if (Input.GetKey(KeyCode.Mouse0))
{
if (Physics.Raycast(_camera.ScreenPointToRay(Input.mousePosition), out _hit, 100f))
{
_drawMaterial.SetVector("_InputPoint", new Vector4(_hit.textureCoord.x, _hit.textureCoord.y, 0, 0));
_drawMaterial.SetFloat("_BrushStrength", _brushStrength);
_drawMaterial.SetFloat("_BrushSize", _brushSize);
}
}
}
private void OnGUI()
{
GUI.DrawTexture(new Rect(0, 0, m_GUIsize, m_GUIsize), _splatmap, ScaleMode.StretchToFill, false, 1);
}
}
CustomRenderTextures and URP do not seem to play nicely together either, at least not in builds, as of 2020.1.2f1. I eventually had to give up and hack a solution together with a dedicated camera, layer and quad, because nothing I tried (and I tried a lot) would persuade the CustomRenderTexture to even initialise in a PC build, despite working perfectly in the editor.
Related
I am trying to make simple sliding puzzel game in unity. I used https://youtu.be/rJFprTG3wE0 this video as tutorial. In the video block move if clicked but mine doesn't.
using UnityEngine;
public class gamebasic : MonoBehaviour
{
[SerializeField] public Transform empty =null;
private Camera _camera;
// Start is called before the first frame update
void Start()
{
_camera = Camera.main;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction);
if (hit)
{
if (Vector2.Distance(a: empty.position, b: hit.transform.position) < 1)
{
Vector2 lastemptyposition = empty.position;
empty.position = hit.transform.position;
hit.transform.position = lastemptyposition;
}
}
}
}
}
Here is my code and I am using visual studio 2017 version 15.9.39 and unity 2020.3.11f1.
At the end of the video he makes a comment about changing the value of the distance, if your reference to the empty transform is correct that might be the reason.
You can make this a public variable and test different values, like this:
[SerializeField] private float maxDistanceToEmpty = 2f;
and then you change that line to
if (Vector2.Distance(a: empty.position, b: hit.transform.position) < maxDistanceToEmpty )
So i made an ball(player) which moves forward on it's own with script. I want to make that ball act like a normal ball. when it riches the edge of platform it won't fall off. Basicaly it stops on the edge. Here's my image:
Here's my controller script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SwerveInputSystem : MonoBehaviour
{
private float _lastFrameFingerPositionX;
private float _moveFactorX;
public float MoveFactorX => _moveFactorX;
void Start(){
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
_lastFrameFingerPositionX = Input.mousePosition.x;
}
else if (Input.GetMouseButton(0))
{
_moveFactorX = Input.mousePosition.x - _lastFrameFingerPositionX;
_lastFrameFingerPositionX = Input.mousePosition.x;
}
else if (Input.GetMouseButtonUp(0))
{
_moveFactorX = 0f;
}
}
}
This is Second script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour{
private SwerveInputSystem _swerveInputSystem;
[SerializeField] private float swerveSpeed = 5f;
[SerializeField] private float maxSwerveAmount = 1f;
[SerializeField] private float verticalSpeed;
void Start(){
_swerveInputSystem = GetComponent<SwerveInputSystem>();
}
void Update(){
float swerveAmount = Time.deltaTime * swerveSpeed * _swerveInputSystem.MoveFactorX;
swerveAmount = Mathf.Clamp(swerveAmount, -maxSwerveAmount, maxSwerveAmount);
transform.Translate(swerveAmount, 0, 0);
float verticalDelta = verticalSpeed * Time.deltaTime;
transform.Translate(swerveAmount, verticalDelta, 0.1f);
}
}
EDITED: Adjusted the answer since we now have some source code.
You are positioning the player directly (using its transform) which will mess up the physics. The purpose of a rigidbody is to let Unity calculate forces, gravity, and so on for you. When you are using physics, and you want to move an object you have three main options:
Teleporting the object to a new position, ignoring colliders and forces like gravity. In this case use the rigidbody's position property.
_ourRigidbody.position = new Vector3(x, y, z);
Moving the object to the new position, similar to teleporting but the movement can be interrupted by other colliders. So, if there is a wall between the object and the new position, the movement will be halted at the wall. Use MovePosition().
_ourRigidbody.MovePosition(new Vector3(x, y, z));
Adding some force to the object and letting the physics engine calculate how the object is moved. There are several options like AddForce() and AddExplostionForce(), etc... see the Rigidbody component for more information.
_ourRigidbody.AddRelativeForce(new Vector3(x, y, z));
In your case you can simply remove the transsform.Translate() calls and instead add some force like this:
//transform.Translate(swerveAmount, 0, 0);
//transform.Translate(swerveAmount, verticalDelta, 0.1f);
Vector3 force = new Vector3(swerveAmount, verticalDelta, 0);
_ourRigidbody.AddForce(force);
We can get the _ourRigidbody variable in the Awake() or Start() method as normal. As you can see I like the Assert checks just to be safe, one day someone will remove the rigidbody by mistake, and then it is good to know about it...
private SwerveInputSystem _swerveInputSystem;
private Rigidbody _ourRigidbody;
void Start()
{
_swerveInputSystem = GetComponent<SwerveInputSystem>();
Assert.IsNotNull(_swerveInputSystem);
_ourRigidbody = GetComponent<Rigidbody>();
Assert.IsNotNull(_ourRigidbody);
}
One likely reason your Rigidbody is not being affected by gravity is due to having the field isKinematic checked to on. From the Rigidbody docs, when toggling on isKinematic,
Forces, collisions or joints will not affect the rigidbody anymore.
The rigidbody will be under full control of animation or script
control by changing transform.position
As gravity is a force and no forces act on the object when this setting is checked, your object will not fall when it is no longer on the platform. A simple solution is to uncheck this box.
I use the objects that I scan with the photogrammetry method exactly in unity. So when I create a cube and expand this cube to the extent that I want to measure, I give an example. The z value gives the value in meters. What I want to do is to measure the distance with an object to be created between the two points I click on the object and the value I will get over it. How can I make this happen?
I've tried the code below but nothing draws.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class olcumYap : MonoBehaviour
{
private LineRenderer lineRend;
private Vector2 mousePos;
private Vector2 startMousePos;
[SerializeField]
private Text distanceText;
private float distance;
// Start is called before the first frame update
void Start()
{
lineRend = GetComponent<LineRenderer>();
lineRend.positionCount = 2;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
if (Input.GetMouseButton(0))
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
lineRend.SetPosition(0, new Vector3(startMousePos.x, startMousePos.y, 0f));
lineRend.SetPosition(1, new Vector3(mousePos.x, mousePos.y, 0f));
distance = (mousePos - startMousePos).magnitude;
distanceText.text = distance.ToString("F2") + "metre";
}
}
}
You could try debugging the line positions to see if the problem is the line renderer or the positions.
Debug.Log(<position>);
print(<position>);
It is generally a good practice to log something if it doesnt work to find the issuee.
I have simple fog shader that works just fine on Forward rendering. However, I need to make it work on deferred rendering too. I was told that I only have to change the script that is calling the shader.
My fog calling C# script:
using UnityEngine;
using UnityEngine.Rendering;
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class Fog : MonoBehaviour
{
public Color fogColor;
public float minDistance;
public float maxDistance;
Shader _shader;
Material _material;
static class Uniforms
{
internal static readonly int _FogColor = Shader.PropertyToID("_FogColor");
internal static readonly int _MinMax = Shader.PropertyToID("_MinMax");
}
public enum BlendMode { Blend, Additive, Multiplicative};
public BlendMode blendMode;
void OnEnable()
{
if (_shader == null) {
_shader = Shader.Find("Hidden/Fog");
}
_material = new Material(_shader);
_material.hideFlags = HideFlags.DontSave;
}
void OnDisable()
{
DestroyImmediate(_material);
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
_material.SetColor(Uniforms._FogColor, fogColor);
_material.SetVector(Uniforms._MinMax, new Vector4(minDistance, maxDistance, 0, 0));
Graphics.Blit(source, destination, _material, (int)blendMode);
}
}
Could you help me to find what exactly do I have to write to make this work with deferred rendering? I have read a lot about this and studied all of the Unity Docs about shaders, but there are no examples on how to use this with image effect shaders.
I'm making a 2D game about launching objects towards eachother. It is almost complete. However, when I run it on different devices, the offsets of certain gameobjects are messed up due to the different screen size. In the Unity editor, I'm using the free aspect view, and I've created my gameobjects so that with a camera size of 80, they all align perfectly. I think the problem here is that the screen resolution messes up the display, and because I'm using a fixed amount of Unity units to position my gameobjects, they are displayed weirdly when I run the game on the standalone. I've written a pixel perfect camera script, but it doesn't seem to help. The camera is pixel perfect, however, in order to compensate, the camera size is turned into something extremely small, or extremely large. I just want the same look across all devices and screen resolutions. A main problem here is that I want my GUI elements to display next to where the player is standing. My script is here.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class HoldTimeMultiplierPlayerFollowController : MonoBehaviour {
public float textYOffset = 50f;
public Text holdTimeMultiplierDisplay;
void Update() {
Vector3 position = Camera.main.WorldToScreenPoint(transform.position);
holdTimeMultiplierDisplay.gameObject.transform.position = new Vector3(position.x, position.y + textYOffset, position.z);
}
}
Anyone got any ideas?
BTW,
all my art is 32x32. The pixels to units ratio is always 1 to 1. The camera size in the editor is 81.92, when I'm using a free aspect screen size of 686x269. At those measurements, everything is displayed perfectly.
Any help is appreciated. Maybe a script, or a suggestion on how to implement it?
Other scripts (If you see any issues that need to be resolved or improvements that could be added, please tell me):
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class PlayerMovementController : MonoBehaviour {
private int holdTimeMultiplier = 0;
public int maxHoldTimeMultiplier = 215;
public Text holdTimeMultiplierDisplayText;
private Rigidbody2D rbody;
void Awake() {
rbody = GetComponent<Rigidbody2D>();
if(rbody == null) {
Debug.LogError ("No Rigidbody2D detected on player.");
}
}
void Update() {
Vector2 mousePosition = new Vector2(Camera.main.ScreenToWorldPoint(Input.mousePosition).x,
Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
Vector2 mouseDirectionFromPlayer = mousePosition - new Vector2(transform.position.x, transform.position.y);
if(Input.GetMouseButton(0)) {
if(holdTimeMultiplier < maxHoldTimeMultiplier) {
holdTimeMultiplier ++;
} else {
holdTimeMultiplier = 0;
}
} else {
if(holdTimeMultiplier != 0) {
rbody.AddForce(mouseDirectionFromPlayer * holdTimeMultiplier * 200);
holdTimeMultiplier = 0;
}
}
holdTimeMultiplierDisplayText.text = holdTimeMultiplier.ToString();
}
}
...
using UnityEngine;
using System.Collections;
public class SpawnNewObject : MonoBehaviour {
public GameObject[] UseableObjects;
public Transform SpawnPoint;
void Update() {
if(Input.GetKeyDown(KeyCode.N)) {
var randomObject = Random.Range(0,UseableObjects.Length);
GameObject UseableObject;
UseableObject = Instantiate(UseableObjects[randomObject], SpawnPoint.position, SpawnPoint.rotation) as GameObject;
}
}
}