HoloLens - Unity: How to change color of cursor? - unity3d

I tried to change the color via script on runtime of the cursor and it worked to 75%:
Mesh_top is the only part that does not change the color and I dont know why.
All 4 parts use the same material, named "cursormaterial".
What I tried:
Changing the color by referencing to cursormaterial
Changing the color by getting the component SkinnedMeshRenderer
Trying to use ProptertyBlock
In all three cases I got the same result. The only thing that works is before hitting play I can change the color, this will change the color of the whole cursor. Changing it on runtime works only for 3 of 4 parts...´
--Edit--
public SkinnedMeshRenderer cursorRendererOne, cursorRendererTwo, cursorRendererThree, cursorRendererFour;
private MaterialPropertyBlock _propBlock;
public Material material;
void Start()
{
_propBlock = new MaterialPropertyBlock();
}
public void OnInputDown(InputEventData eventData)
{
if (!isActivated)
{
//#1
material.color = Color.blue;
//#2
cursorRendererOne.sharedMaterial.color = Color.blue;
//#3
cursorRendererOne.GetPropertyBlock(_propBlock);
_propBlock.SetColor("_Color", Color.blue);
cursorRendererOne.SetPropertyBlock(_propBlock);
cursorRendererTwo.SetPropertyBlock(_propBlock);
cursorRendererThree.SetPropertyBlock(_propBlock);
cursorRendererFour.SetPropertyBlock(_propBlock);
isActivated = true;
}
Here u see the changed material, but the mesh_top looks but different:

This is a "Bug" (maybe an intended one?).
Open the Animation window (CTRL + 6)
And in the hierachy select the CursorVisual
If you now go to the animation called CursorWaitingAnim you can see there is a keyframe for the top_mesh color.
This single keyframe causes that the color of that tile can not be changed on runtime. The reason is that the animator runs after OnInputDown so it reverts the changes for any keyframed property.
So if you don't need the Waiting animation simply remove that keyframe.
=> you can manipulate the color at runtime again!
Alternatively you could replace it by a one that instead of fixing the color simply disables the SkinnedMeshRenderer instead which basically has more or less the same effect but doesn't screw the colors:

Related

Graphics.RenderTexture() causes extra image to appear on canavas

I have some code like this:
readonly Rect WORK_SOURCE_RECT = new Rect(0f, 0f, 1f, 1f);
Color[] workPixels;
void Start() {
Texture2D workTexture = new Texture2D(256, 256, GraphicsFormat.R8G8B8A8_UNorm,
TextureCreationFlags.None);
workPixels = workTexture.GetPixels();
}
void OnGUI() {
workTexture.SetPixels(workPixels);
workTexture.Apply();
Graphics.DrawTexture(toRect, workTexture, WORK_SOURCE_RECT,
0, 0, 0, 0, renderColor);
}
void Update() {
// Omitted - Some changes are made by code here to the workPixels array.
}
The call to Graphics.DrawTexture() correctly draws the content of workTexture to the screen, just how I want it. But there is a strange side effect...
Any other GUI that is drawn inside of a scene object containing a Canvas component, will show an extra Y-reversed copy of the work texture. (Nevermind the reversal--not the issue.) I don't know why this extra image is drawn. It seems like there is a shared resource between two GUI things I'd hoped were completely unrelated.
In the image shown below, the reversed-face on the right is the unwanted extra render. Strangely it appears when I move to the right side of my scene, so it's like it is in world space. But it will update when GUI-based elements like subtitles are shown.
On Unity 2019.4.13f1 with MacOS.
The solution I found that resolved my problem was camera stacking. I created a second camera that was culled to just UI layer. The first camera had UI layer removed from culling. And then the calls to Graphics.DrawTexture() no longer appeared on the canvas used for UI.

Unity - How to change AnimationClip KeyFrame values at runtime

is it possible to change keyframe values from a clip at runtime via script in Unity3d? (non-legacy)
I want to change the value of the "Body > arm" - rotation.z. There are 3 keyframes at the normal clip and i want to change the only the 2nd keyframe value to maybe 120f.
At the Screenshot below you can see my "RightArm" Property (first keyframe value is 0). The result have to be, when i rise my mouse (position.y is maybe also 120), the arm has to follow while hes in this animationclip.
I hope i descriped my problem enough, that you can understand it. Every google solution and many code examples doesnt work...
Thanks!
My Unity Version: 2019.2.8
You can use AnimationClip.SetCurve(string relativePath, Type type, string propertyName, AnimationCurve curve)
where
relativePath
Path to the game object this curve applies to. The relativePath is formatted similar to a pathname, e.g. "root/spine/leftArm". If relativePath is empty it refers to the GameObject the Animation/Animator component is attached to.
In your case probably something like "Body/RightShoulder/RightArm"
type
The class type of the component that is animated.
In your case typeof(Transform)
propertyName
The name or path to the property being animated.
Note that for Unity built-in components the names of the properties sometimes differ from what is displayed in the Inspector! Always refer to the API.
in your case localRotation
curve
The animation curve.
(Modified) Example from the documentation:
public AnimationClip clip;
private void Start()
{
// create a curve to move the GameObject and assign to the clip
Keyframe[] keys;
keys = new Keyframe[3];
keys[0] = new Keyframe(0.0f, 0.0f);
// within 12 seconds rotate to 120°
keys[1] = new Keyframe(12.0f, 120f);
// Whatever you need as 3. keyframe
keys[2] = new Keyframe(16.0f, 0f);
var curve = new AnimationCurve(keys);
clip.SetCurve("Body/RightShoulder/RightArm", typeof(Transform), "localRotation.z", curve);
}
Also see Keyframe and AnimationCurve
Note:
Unfortunately it is not possible to get an existing curve (at least not trivial) so you always have to set one from scratch.

Adding Animation to Inputfield and save the transform

I wanted to add a simple search animation to my input field in my unity UI.
This is my InputField and the idea is, when I select it, it should expand slowly, and when I deselect it, it should shrink back to its normal form.
This is the rect Transform Component of this inputfield. I added to the input field and Event Trigger Component and an Animator. I created two Animations called SearchAnimation and DeselectAnimation and added them to my AnimationController called 'SearchController'.
This is how I designed my SearchController:
I set the Transitions between the defaultState and SearchAnimation to be listening to the SelectBool and DeselectBool (the name already describes its purpose).
Then I added the following script to my input Field so that those two booleans will be set accordingly to the event trigger:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class OnClickScript : MonoBehaviour {
Animator anim;
void Start()
{
anim = GetComponent<Animator>();
}
public void OnSelect()
{
anim.SetBool("SelectBool", true);
anim.SetBool("DeselectBool", false);
GetComponent<RectTransform>().sizeDelta = new Vector2(450, 50);
GetComponent<RectTransform>().localPosition.Set(-275, 0, 0);
}
public void OnDeselect()
{
anim.SetBool("DeselectBool", true);
anim.SetBool("SelectBool", false);
GetComponent<RectTransform>().sizeDelta = new Vector2(200, 50);
GetComponent<RectTransform>().localPosition.Set(-130, 0, 0);
}
}
But after the animation is played the inputfield is set back to its inital size and location. How do I fix this?
Easy way:
Create one more clips. The clip is made of only one key which is the Size Delta of the SelectedState. Then make this clip the animation clip of the state.
I put my test project here.
With above approach, once you want to change the size of default state and selected state, you will have to change all four animation clips manually.
Hard way
Using AnimationClip.SetCurve to create animation from the script. With this approach, you can create more maintainable animations. But it's not easy to create complex animations with scripts.
Suggestions:
Using Pivot:
In the script, you are changing local position to prevent the input field moving up. Instead of changing the local position value, you can set the pivot Y to 1 if you want the input field to expand downward.
Using trigger:
Instead of using two bool variables, you can simply use one Trigger to trigger the animation start and move to next state.

Get particle gradient color

I see how to set a particle's color based on a gradient (e.g. this & this) but I can't find anything on how to get the color.
I have a particle system with the start color set to random with a gradient. I've tried...
Color myColor = myParticleSystem.main.startColor.color
... but it always returns black, regardless of the gradient colors.
I don't see anything in the docs or forums about how to actually get the color that was randomly chosen.
Using Unity 2017.3. Thanks.
At the moment, we can't read the MinMaxCurve from scripts, as per here: https://blogs.unity3d.com/2016/04/20/particle-system-modules-faq/ (scroll down to the Easing the Pain section).
However, your code returns not a MinMaxCurve, but the Start Color of type Color that you can set via inspector or via script.
For example, if you create a Particle System game object in a scene, and you attach to it this simple script:
using UnityEngine;
public class ParticlesTest : MonoBehaviour {
ParticleSystem myParticleSystem;
public Color myColor;
private void Awake() {
myParticleSystem = GetComponent<ParticleSystem>();
}
private void Update() {
myColor = myParticleSystem.main.startColor.color;
}
}
you can see that myColor changes when you change the Start Color value of the Particle System in Play mode.

Move a particular sprite to a target position after clicking the button in unity 4.6

I have just started unity. I have 4 Images(sprites) aligned in a grid.
As soon as i touch the particular chocolate, its texture changes[I wrote a code for that]. There is a button on screen.After pressing the button, I want to move only those chocolates whose texture has been changed.
I know the following move code but i don't know how to use it here.
void Update () {
float step=speed*Time.deltaTime;
transform.position=Vector3.MoveTowards(transform.position,target.position,step);
}
I just don't know to move that particular sprite whose texture is changed. Thanks
Do you want to be moving the sprites over the course of a duration or instantly?
If it's over the course of a duration I suggest you use Lerp. You can Lerp between two Vector.3's in a time scale. Much cleaner and once learned a very useful function.
Code examples below:
http://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
http://www.blueraja.com/blog/404/how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly
However if you want to move it instantly. This can be done very easily using the built in localPosition properties which you can set in or outside the object.
Set your changed sprites Bool moved property (create this) to true on click (if you're using Unity 4.6 UI canvas then look at the IClick interfaces available for registering mouse activity in canvas elements) and then when you press the button, loop through a list in a handler file which contains all your button texture objects and move those that the moved property is set to true for.
foreach(GameObject chocolate in chocolateList)
{
if (chocolate.moved == true)
{
gameObject.transform.localPosition.x = Insert your new x position.
gameObject.transform.localPosition.y = Insert your new y position.
}
}
However please do clarify your intentions so I can help further.
EDIT 1:
I highly suggest you make your sprites an object in the canvas for absolute work clarity. This makes a lot of sense as your canvas can handle these type of things much better. Use Image and assign your image the sprite object (your chocolate piece), define it's width and height and add a script to it called "ChocolatePiece", in this script create two public variables, bool moved and int ID, nothing else is required from this script. Save this new object as your new prefab.
Once you've done this in a handler script attached to an empty gameobject in your canvas make a list of gameobjects:
List<GameObject> chocolatePieces = new List<GameObject>();
You'll want to at the top of your handler script define GameObject chocolatePiece and attach in your inspector the prefab we defined earlier. Then in Start(), loop the size of how many chocolate pieces you want, for your example lets use 4. Instantiate 4 of the prefabs you defined earlier as gameobjects and for each define their properties just like this:
Example variables:
int x = -200;
int y = 200;
int amountToMoveInX = 200;
int amountToMoveInY = 100;
Example instantiation code:
GameObject newPiece = (GameObject)Instantiate(chocolatePiece);
chocolatePieces.Add(newPiece);
newPiece.GetComponent<ChocolatePiece>().ID = i;
newPiece.transform.SetParent(gameObject.transform, false);
newPiece.name = ("ChocolatePiece" + i);
newPiece.GetComponent<RectTransform>().localPosition = new Vector3(x, y, 0);
From this point add to your positions (x by amountToMoveInX and y by amountToMoveInY) for the next loop count;
(For the transform.position, each count of your loop add an amount on to a default x and default y value (the position of your first piece most likely))
Now because you have all your gameobjects in a list with their properties properly set you can then access these gameobjects through your handler script.