Change material on click Unity3D - unity3d

I am trying to change material rendered on a cube upon click. Simple if else condition (I believe). I have tried
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Debug.Log("Click");
if (GetComponent<Renderer>().material == brick)
{
Debug.Log("Brick");
GetComponent<Renderer>().material = normal;
}
else if(GetComponent<Renderer>().material == normal)
{
Debug.Log("Normal");
GetComponent<Renderer>().material = brick;
}
}
}
I am getting in the first loop ie GetMouseButtonDown. But Nothing happens to the cube after that. no errors or warnings.

I would rather use a bool flag instead of checking the material reference
// Set the initial value via the Inspector
// to decide whether this should start as brick or normal
[SerializeField] private bool isBrick;
// If possible already drag in the renderer via the Inspector
[SerializeField] private Renderer _renderer;
// If ever needed later let others know directly whether this is a brick
// this property allows read-only acccess
public bool IsBrick => isBrick;
private void Awake ()
{
// As fallback get the renderer ONCE on runtime
if(!_renderer) _renderer = GetComponent<Renderer>();
// Apply the initial state
_renderer.material = isBrick ? brick : normal;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Debug.Log("Click");
Debug.Log(isBrick ? "Brick" : "Normal");
// Invert the bool flag
isBrick = !isBrick;
// Apply the new state
_renderer.material = isBrick ? brick : normal;
}
}

Related

Unity renders object before updating Rigidbody2D's properties

I am trying to implement a way for the player to switch between a square and a circle. For this to work my player object has two colliders, one circle and one box. When switching between them I simply disable one collider and enable the other, and switch the current sprite. The issue arises when I switch from a circle to a square.
I want the square to be able to glide across the floor, whereas the circle is supposed to roll. In order to make the switch seamless I have to reorient the square to be aligned with the current velocity, and remove the angular velocity. This does seem to work, however there is a slight period of frames (or frame) where the square has the same rotation the circle had before switching. This seems odd to me since the new rotation and sprite is changed in the same part of the code. This is a video showcasing the issue.
If this is an issue resulting from the way the objects are rendered I can solve this another way. I would just like to understand why it happens.
Code snippet of the part that changes the properties from circle to square when switching:
else if (Input.GetKeyDown("2"))
{
// Update rotation of box to velocity:
float newAngleRadians = Mathf.Atan2(rb.velocity.y, rb.velocity.x);
float newAngleDegrees = newAngleRadians * 180 / Mathf.PI;
rb.rotation = newAngleDegrees;
rb.angularVelocity = 0;
Debug.Log(rb.rotation);
playerShape = Shape.SQUARE;
spriteRenderer.sprite = spriteArray[1];
circleCollider.enabled = false;
boxCollider.enabled = true;
updateShape = true;
}
Logging the angle of the rigidbody directly after setting it to newAngleDegrees shows that the rotation has been set correct, yet the issue persists.
And just in case it is needed, full code of the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class scr_StateMachine : MonoBehaviour
{
// Types of shapes:
public enum Shape { SQUARE, CIRCLE, TRIANGLE }
// Variables:
public Rigidbody2D rb;
public SpriteRenderer spriteRenderer;
public Sprite[] spriteArray;
public Shape playerShape;
public CircleCollider2D circleCollider;
public BoxCollider2D boxCollider;
private bool updateShape;
void Start()
{
playerShape = Shape.CIRCLE;
updateShape = true;
}
void Update()
{
// Get input for shape change:
if(Input.GetKeyDown("1"))
{
playerShape = Shape.CIRCLE;
spriteRenderer.sprite = spriteArray[0];
circleCollider.enabled = true;
boxCollider.enabled = false;
updateShape = true;
}
else if (Input.GetKeyDown("2"))
{
// Update rotation of box to velocity:
float newAngleRadians = Mathf.Atan2(rb.velocity.y, rb.velocity.x);
float newAngleDegrees = newAngleRadians * 180 / Mathf.PI;
rb.rotation = newAngleDegrees;
rb.angularVelocity = 0;
Debug.Log(rb.rotation);
playerShape = Shape.SQUARE;
spriteRenderer.sprite = spriteArray[1];
circleCollider.enabled = false;
boxCollider.enabled = true;
updateShape = true;
}
// Update movement script's shape:
if (updateShape)
{
GetComponent<scr_Movement>().shape = playerShape;
updateShape = false;
}
}
}
I think the issue is Rigidbody/Rigidbody2D physics are applied in fixed time steps (see FixedUpdate). Therefore yes, on a strong device it can definitely happen that you render some frames before the next FixedUpdate call kicks in and changes the Rigidbody/Rigidbody2D behavior.
I think what you could do is actually wait with the change for the next FixedUpdate call e.g. using a Coroutine and WaitForFixedUpdate like e.g.
public class scr_StateMachine : MonoBehaviour
{
// Types of shapes:
public enum Shape { SQUARE, CIRCLE, TRIANGLE }
// Variables:
public Rigidbody2D rb;
public SpriteRenderer spriteRenderer;
public Sprite[] spriteArray;
public Shape playerShape;
public CircleCollider2D circleCollider;
public BoxCollider2D boxCollider;
[SerializeField] private scr_Movement _scrMovement;
void Start()
{
if(!_scrMovement) _scrMovement = GetComponent<scr_Movement>();
ChangeShape(Shape.CIRCLE);
}
// Still get User Input in Update
void Update()
{
// Get input for shape change:
if(Input.GetKeyDown("1"))
{
ChangeShape(Shape.CIRCLE);
}
else if (Input.GetKeyDown("2"))
{
ChangeShape(Shape.SQUARE);
}
}
private void ChangeShape(Shape newShape)
{
// if the same shape comes in we already have -> nothing to do
if(newShape == playerShape) return;
// Stop any already running coroutine since we only want to handle the last input before the FixUpdate call
// https://docs.unity3d.com/ScriptReference/MonoBehaviour.StopAllCoroutines.html
StopAllCoroutines();
// Start a new coroutine for the new shape
// see https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html
StartCoroutine(ChangeShapeInNextFixedUpdate(newShape));
}
private IEnumerator ChangeShapeInNextFixedUpdate(Shape newShape)
{
// just in case again, if the same shape comes in we already have -> nothing to do
if(newShape == playerShape) yield break;
// Wait until the next FixedUpdate call
// see https://docs.unity3d.com/ScriptReference/WaitForFixedUpdate.html
yield return new WaitForFixedUpdate();
// Now do your required changes depending on the new shape
circleCollider.enabled = newShape == Shape.CIRCLE;
boxCollider.enabled = newShape == Shape.SQUARE;
switch(newShape)
{
case Shape.CIRCLE:
spriteRenderer.sprite = spriteArray[0];
break;
case Shape.SQUARE:
// Update rotation of box to velocity:
var newAngleRadians = Mathf.Atan2(rb.velocity.y, rb.velocity.x);
// see https://docs.unity3d.com/ScriptReference/Mathf.Rad2Deg.html
var newAngleDegrees = newAngleRadians * Mathf.Rad2Deg;
rb.rotation = newAngleDegrees;
rb.angularVelocity = 0;
Debug.Log(rb.rotation);
spriteRenderer.sprite = spriteArray[1];
break;
}
playerShape = newShape;
_scrMovement.shape = playerShape;
}
}

How do I stop my objects from going through walls when I pick them up and drop them down?

When I pick an object up I can glitch it through the map making it fall out of the world. This happens when I pick it up and drop the object half way through the floor. The outcome I receive is not what I was expecting what can I do to fix this. Also yes the colliders and rigidbody's are setup correctly.
public GameObject PressEtoInteractText;
public bool pickup, inrange;
public Collider Playercol;
public Vector3 guide;
private GameObject temp;
private Rigidbody rb;
void Update()
{
if (Input.GetKeyDown(KeyCode.E) && inrange == true)
{
PressEtoInteractText.SetActive(false);
pickup = true;
}
if (Input.GetMouseButtonDown(0) && pickup == true)
{
pickup = false;
Playercol.isTrigger = true;
}
UpdatePickUpFollow();
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Interact")
{
PressEtoInteractText.SetActive(true);
temp = other.gameObject;
inrange = true;
}
if (other.gameObject.tag == "Interact" && temp.transform.position == guide)
{
return;
}
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.name != "Interact")
{
PressEtoInteractText.SetActive(false);
inrange = false;
}
}
public void PickUp()
{
rb = temp.GetComponent<Rigidbody>();
rb.MovePosition(transform.position += guide);
Playercol.isTrigger = false;
}
public void UpdatePickUpFollow()
{
if (pickup == true)
{
PickUp();
}
}
If you deactivate the objects collider with tempCol.enabled = false; it will not register any collisions and you can just push or pull it through walls all day. Make sure to remove that from your script.
Also, using MoveTowards can cause issues with collision detection. In my experience it is best to use AddForce or MovePosition to move the Rigidbody component instead of modifying the Transform directly. Try Rigidbody.MovePosition(Vector3 position). Maybe this works better for you.
Here is a link to the documentation page. It's basically your exact use case:
Rigidbody.MoveTowards Unity Docs
(Hint: notice how they use FixedUpdate instead of regular Update. You should also always do this when working with Rigidbodies because it is synced with physics updates.)
//Edit:
This is a little implementation of your code in a cleaner and hopefully correct way. I have not tested this and there is propably something I missed. Use this as a reference to build your own working solution.
//set in inspector
public Transform guidePosition;
public GameObject pressEToInteractText;
private bool isObjectInRange;
private GameObject inRangeObject;
private bool isObjectPickedUp;
private Rigidbody pickedUpRigidBody;
/* check if button is pressed.
* If no object is in hand -> pick up;
* if object is in hand -> drop;
*/
private void FixedUpdate()
{
if (Input.GetKeyDown(KeyCode.E) && isObjectInRange && !isObjectPickedUp)
{
PickupObject();
}
if(Input.GetKeyDown(KeyCode.E) && isObjectPickedUp)
{
DropObject();
}
if (isObjectPickedUp)
{
PickedUpObjectFollow();
}
}
//save references
private void PickupObject()
{
pickedUpRigidBody = inRangeObject.GetComponent<Rigidbody>();
isObjectPickedUp = true;
}
//remove saved references
private void DropObject()
{
isObjectPickedUp = false;
pickedUpRigidBody = null;
}
//move position to guidePosition
private void PickedUpObjectFollow()
{
pickedUpRigidBody.MovePosition(guidePosition.position);
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Interact") && !isObjectPickedUp)
{
pressEToInteractText.SetActive(true);
isObjectInRange = true;
inRangeObject = other.gameObject;
}
}
private void OnTriggerExit(Collider other)
{
if(other.CompareTag("Interact") && other.gameObject == inRangeObject)
{
pressEToInteractText.SetActive(false);
isObjectInRange = false;
inRangeObject = null;
}
}
You could do multiple things. Unfortunately the way VR tracks the hands and there is no way to stop ur hands in real life your hand will defy the physics in the application.
I would either make the item drop from the users hand when it gets close enough to a certain area that you dont want it going through.
Or you can make it that if it does pass through a space you can report the item right above the floor it went through.
Ive looked long and hard for an answer to this and it doesnt seem like it can at this point be blocked from moving through if its currently grabbed.

How to get screen click input from anywhere with custom editor attribute?

TL;DR: How do I implement Unity's 'color from screen' functionality but with vectors?
Ok so title is pretty simplified for what I'm trying to do:
Have the user click a button, then click a position on the screen to have that [world] position be saved as the vector. - This is mostly working, except it won't detect left clicks outside of the inspector.
Disable left click for everything else on the unity editor (so when you click a position it doesn't change focus to another GameObject). - This is the main problem.
Tracking the mouse and getting the world position was pretty easy, it's just a bool to save if the mouse is being tracked and a SerializedProperty to save which value the mouse position is being saved to.
Here's what my attribute looks like:
public class VectorPickerAttribute : PropertyAttribute {
readonly bool relative;
/// <summary>
/// Works a lot like the color picker, except for vectors.
/// </summary>
/// <param name="relative">Make the final vector relative to the transform?</param>
public VectorPickerAttribute(bool relative = false) {
this.relative = relative;
}
}
Here is the PropertyDrawer:
[CustomPropertyDrawer(typeof(VectorPickerAttribute))]
public class VectorPickerDrawer : PropertyDrawer {
bool trackMouse = false;
SerializedProperty v;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
if(property.propertyType == SerializedPropertyType.Vector2) {
Rect button = new Rect(position);
button.x = position.width - 2;
button.width = position.height;
bool pressed = GUI.Button(button, "");
if(pressed) {
trackMouse = true;
v = property;
}
else if(Input.GetMouseButtonDown(0)) trackMouse = false;
bool tracking = trackMouse && v.propertyPath == property.propertyPath;
if(tracking) {
property.vector2Value =
Camera.main.ScreenToWorldPoint(
GUIUtility.GUIToScreenPoint(
Event.current.mousePosition
));
}
GUI.enabled = !tracking;
EditorGUI.Vector2Field(position, label.text, property.vector2Value);
GUI.enabled = true;
EditorUtility.SetDirty(property.serializedObject.targetObject);
}
}
}
And here's what it does so far:
You click the button on the right, and it will update the vector to the mouse position until it detects a left click with Input.GetMouseButtonDown(0).
Problems with this:
It will only detect a click when it's actually on the inspector window.
When you click outside the inspector window it will either not change anything or it will select something else so it will close the inspector (but since it saves the mouse position every OnGUI() that point where you clicked will be saved to the vector, so I guess it works??).
I've tried covering the screen with a blank window, but I couldn't get GUI.Window or GUI.ModalWindow to do anything in the PropertyDrawer. I've also tried using GUI.UnfocusWindow(), but either it doesn't work in PropertyDrawer or it's only meant for Unity's windows or something.
Core aspects:
overwrite SceneView.onSceneGUIDelegate in order to catch any mouse events on the SceneView
use ActiveEditorTracker.sharedTracker.isLocked to lock and unlock the inspector to prevent losing the focus (which would cause the OnGUI not getting called anymore)
use Selection.activeGameObject and set it to the GameObject the drawer is on in order to prevent losing the focus on the GameObject (especially in the moment ActiveEditorTracker.sharedTracker.isLocked is set to false it seems to automatically clear Selection.activeGameObject)
Allow reverting the value to previous using the Escape key
Use Event.current.Use(); and/or Event.current = null; (I just wanted to be very sure) in order to prevent the event to propagate and being handled by someone else
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Attribute for setting a vector by clicking on the screen in editor mode.
/// </summary>
public class VectorPickerAttribute : PropertyAttribute {
public readonly bool relative;
/// <summary>Works a lot like the color picker, except for vectors.</summary>
/// <param name="relative">Make the final vector relative the transform?</param>
public VectorPickerAttribute(bool relative = false) {
this.relative = relative;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(VectorPickerAttribute))]
public class VectorPickerDrawer : PropertyDrawer {
#region Variables
bool _trackMouse;
SerializedProperty _property;
MonoBehaviour script;
///<summary>Keep the currently selected object to avoid loosing focus while/after tracking</summary>
GameObject _mySelection;
///<summary>For reverting if tracking canceled</summary>
Vector2 _originalPosition;
///<summary>Flag for doing Setup only once</summary>
bool _setup;
/// <summary>Mouse position from scene view into the world.</summary>
Vector2 worldPoint;
#endregion
/// <summary>
/// Catch a click event while over the SceneView
/// </summary>
/// <param name="sceneView">The current scene view => might not work anymore with multiple SceneViews</param>
private void UpdateSceneView(SceneView sceneView) {
Camera cam = SceneView.lastActiveSceneView.camera;
worldPoint = Event.current.mousePosition;
worldPoint.y = Screen.height - worldPoint.y - 36.0f; // ??? Why that offset?!
worldPoint = cam.ScreenToWorldPoint(worldPoint);
VectorPickerAttribute vectorPicker = attribute as VectorPickerAttribute;
if(script != null && vectorPicker.relative) worldPoint -= (Vector2)script.transform.position;
// get current event
var e = Event.current;
// Only check while tracking
if(_trackMouse) {
if((e.type == EventType.MouseDown || e.type == EventType.MouseUp) && e.button == 0) {
OnTrackingEnds(false, e);
}
else {
// Prevent losing focus
Selection.activeGameObject = _mySelection;
}
}
else {
// Skip if event is Layout or Repaint
if(e.type == EventType.Layout || e.type == EventType.Repaint) return;
// Prevent Propagation
Event.current.Use();
Event.current = null;
// Unlock Inspector
ActiveEditorTracker.sharedTracker.isLocked = false;
// Prevent losing focus
Selection.activeGameObject = _mySelection;
// Remove SceneView callback
SceneView.onSceneGUIDelegate -= UpdateSceneView;
}
}
/// <summary>
/// Called when ending Tracking
/// </summary>
/// <param name="revert">flag whether to revert to previous value or not</param>
/// <param name="e">event that caused the ending</param>
/// <returns>Returns the vector value of the property that we are modifying.</returns>
private Vector2 OnTrackingEnds(bool revert, Event e) {
e.Use();
Event.current = null;
//Debug.Log("Vector Picker finished");
if(revert) {
// restore previous value
_property.vector2Value = _originalPosition;
//Debug.Log("Reverted");
}
// disable tracking
_trackMouse = false;
// Apply changes
_property.serializedObject.ApplyModifiedProperties();
return _property.vector2Value;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
script = (MonoBehaviour)property.serializedObject.targetObject;
if(property.propertyType != SerializedPropertyType.Vector2) {
EditorGUI.HelpBox(position, "This Attribute requires Vector2", MessageType.Error);
return;
}
var e = Event.current;
if(!_setup) {
// store the selected Object (should be the one with this drawer active)
_mySelection = Selection.activeGameObject;
_property = property;
_setup = true;
}
// load current value into serialized properties
_property.serializedObject.Update();
//specific to the ONE property we are updating
bool trackingThis = _trackMouse && property.propertyPath == _property.propertyPath;
GUI.enabled = !trackingThis;
EditorGUI.PropertyField(position, property, label);
GUI.enabled = true;
// Write manually changed values to the serialized fields
_property.serializedObject.ApplyModifiedProperties();
if(!trackingThis) {
var button = new Rect(position) {
x = position.width - 2,
width = position.height
};
// if button wasn't pressed do nothing
if(!GUI.Button(button, "")) return;
// store current value in case of revert
_originalPosition = _property.vector2Value;
// enable tracking
_property = property;
_trackMouse = true;
// Lock the inspector so we cannot lose focus
ActiveEditorTracker.sharedTracker.isLocked = true;
// Prevent event propagation
e.Use();
//Debug.Log("Vector Picker started");
return;
}
// <<< This section is only reached if we are in tracking mode >>>
// Overwrite the onSceneGUIDelegate with a callback for the SceneView
SceneView.onSceneGUIDelegate = UpdateSceneView;
// Set to world position
_property.vector2Value = worldPoint;
// Track position until either Mouse button 0 (to confirm) or Escape (to cancel) is clicked
var mouseUpDown = (e.type == EventType.MouseUp || e.type == EventType.MouseDown) && e.button == 0;
if(mouseUpDown) {
// End the tracking, don't revert
property.vector2Value = OnTrackingEnds(false, e);
}
else if(e.type == EventType.KeyUp && _trackMouse && e.keyCode == KeyCode.Escape) {
// Cancel tracking via Escape => revert value
property.vector2Value = OnTrackingEnds(true, e);
}
property.serializedObject.ApplyModifiedProperties();
//This fixes "randomly stops updating for no reason".
EditorUtility.SetDirty(property.serializedObject.targetObject);
}
}
I tried to explain everything in the comments. Ofcourse this still has some flaws and might not work in some special cases but I hope it gets in the correct direction.

Unity Jumping Issue - Character won't jump if it walks to the platform

(This is a 2D project)
I have a jumping issue where if my character WALKS into an X platform, she won't jump, but when she JUMPS ONTO the X platform, she can perform a jump.
For the platforms I am currently using 2 Box Collider 2Ds (one with "is trigger" checked)
For the character I am currently using 2 Box Collider 2Ds (one with "is trigger" checked) and Rigidbody 2D.
Below is the code for jumping and grounded I am currently trying to use.
{
public float Speed;
public float Jump;
bool grounded = false;
void Start()
{
}
void Update()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
if (grounded)
{
GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, Jump);
}
}
}
void OnTriggerEnter2D()
{
grounded = true;
}
void OnTriggerExit2D()
{
grounded = false;
}
}
Issue arises on the same part of every platform. (Each square represents a single platform sprite and they have all the same exact characteristics, since I copy pasted each one of them). Please check the photo on this link: https://imgur.com/a/vTmHw
It happens because your squares have seperate colliders. Imagine this:
There are two blocks : A and B. You are standing on block A. Now you try to walk on block B. As soon as your Rigidbody2D collider touches block B, your character gets an event OnTriggerEnter2D(...). Now you claim, that you are grounded.
However, at this moment you are still colliding with block A. As soon as your Rigidbody2D no longer collides with block A, your character receives OnTriggerExit2D(...). Now you claim, that you are no longer grounded. But in fact, you are still colliding with block B.
Solution
Instead of having bool variable for checking if grounded, you could have byte type variable, called collisionsCounter:
Once you enter a trigger - increase the counter.
Once you exit a trigger - decrease the counter.
Do some checking to make sure you are actually above the collider!
Now, once you need to check if your character is grounded, you can just use
if (collisionsCounter > 0)
{
// I am grounded, allow me to jump
}
EDIT
Actually, after investingating question further, I've realized that you have totally unnecessary colliders (I'm talking about the trigger ones). Remove those. Now you have only one collider per object. But to get the calls for collision, you need to change:
OnTriggerEnter2D(...) to OnCollisionEnter2D(Collision2D)
OnTriggerExit2D(...) to OnCollisionExit2D(Collision2D)
Final code
[RequireComponent(typeof(Rigidbody2D))]
public sealed class Character : MonoBehaviour
{
// A constant with tag name to prevent typos in code
private const string TagName_Platform = "Platform";
public float Speed;
public float Jump;
private Rigidbody2D myRigidbody;
private byte platformCollisions;
// Check if the player can jump
private bool CanJump
{
get { return platformCollisions > 0; }
}
// Called once the script is started
private void Start()
{
myRigidbody = GetComponent<Rigidbody2D>();
platformCollisions = 0;
}
// Called every frame
private void Update()
{
// // // // // // // // // // // // // //
// Need to check for horizontal movement
// // // // // // // // // // // // // //
// Trying to jump
if (Input.GetKeyDown(KeyDode.UpArrow) && CanJump == true)
Jump();
}
// Called once Rigidbody2D starts colliding with something
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.collider.tag == TagName_Platform)
platformCollisions++;
}
// Called once Rigidbody2D finishes colliding with something
private void OnCollisionExit2D(Collision2D collision)
{
if(collision.collider.tag == TagName_Platform)
platformCollisions--;
}
// Makes Character jump
private void Jump()
{
Vector2 velocity = myRigidbody.velocity;
velocity.y = Jump;
myRigidbody.velocity = velocity;
}
}
Here can be minor typos as all the code was typed inside Notepad...
I think there are a couple of issues here.
Firstly, using Triggers to check this type of collision is probably not the best way forward. I would suggested not using triggers, and instead using OnCollisionEnter2D(). Triggers just detect if the collision space of two objects has overlapped each other, whereas normal collisions collide against each otehr as if they were two solid objects. Seen as though you are detecting to see if you have landed on the floor, you don't want to fall through the floor like Triggers behave.
Second, I would suggest using AddForce instead of GetComponent<Rigidbody2D>().velocity.
Your final script could look like something like this:
public class PlayerController : MonoBehaviour
{
public float jumpForce = 10.0f;
public bool isGrounded;
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void OnCollisionEnter2D(Collision2D other)
{
// If we have collided with the platform
if (other.gameObject.tag == "YourPlatformTag")
{
// Then we must be on the ground
isGrounded = true;
}
}
void Update()
{
// If we press space and we are on the ground
if(Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
// Add some force to our Rigidbody
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
// We have jumped, we are no longer on the ground
isGrounded = false;
}
}
}

How to do "highlighting" on gameObject

I'm making an block-like game and now I want to implement highlighting block (gameobject) while there is mouseOver that specific block.
I tried something like this (I'm not sure that this is best way to do this, but it's only one I got idea for):
#pragma strict
public class BlockSelecting extends MonoBehaviour {
public var hovering : boolean = false;
public var xpos : float;
public var ypos : float;
function Start () {
}
function Update () {
}
function OnMouseExit () {
hovering = false;
}
function OnMouseOver ()
{
hovering = true;
xpos = Input.mousePosition.x;
ypos = Input.mousePosition.y;
}
function OnGUI ()
{
GUI.DrawTexture(new Rect(xpos, xpos, 26, 26), (Resources.Load("highlight") as Texture2D));
}
}
This is not working, since Texture is not showing where mouse pointer is. Is there something I can't see or is this wrong way to do this? My highlight resource is just an 26x26 (block is 25x25) 2D texture of transparent rectangle, so it looks like it's highlighted...
P.S. My plan is to use hovering boolean to check if player is still hovering, if not texture should be deleted/hidden (any ideas on how to do this?).
lets say you want to change the color of the object that mouse is on to red so
you should use OnMouseEnter to check if mouse is on your object and OnMouseExit for when mouse exits the objects area and we set the it`s color back to its original color that was before changing it
private color tempColor;
void OnMouseEnter()
{
tempColor = renderer.material.color;
renderer.material.color = Color.red;
}
void OnMouseExit()
{
renderer.material.color = tempColor;
}