如何从脚本访问着色器变量?

How can I access shader variables from script?

着色器:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Outlined/Silhouetted Diffuse" {
     Properties {
         _Color ("Main Color", Color) = (.5,.5,.5,1)
         _OutlineColor ("Outline Color", Color) = (0,0,0,1)
         _Outline ("Outline width", Range (0.0, 0.03)) = .005
         _MainTex ("Base (RGB)", 2D) = "white" { }
     }

 CGINCLUDE
 #include "UnityCG.cginc"

 struct appdata {
     float4 vertex : POSITION;
     float3 normal : NORMAL;
 };

 struct v2f {
     float4 pos : POSITION;
     float4 color : COLOR;
 };

 uniform float _Outline;
 uniform float4 _OutlineColor;

 v2f vert(appdata v) {
     // just make a copy of incoming vertex data but scaled according to normal direction
     v2f o;
     o.pos = UnityObjectToClipPos(v.vertex);

     float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
     float2 offset = TransformViewToProjection(norm.xy);

     o.pos.xy += offset * o.pos.z * _Outline;
     o.color = _OutlineColor;
     return o;
 }
 ENDCG

     SubShader {
         Tags { "Queue" = "Transparent" }

         // note that a vertex shader is specified here but its using the one above
         Pass {
             Name "OUTLINE"
             Tags { "LightMode" = "Always" }
             Cull Off
             ZWrite Off
             ZTest Always
             ColorMask RGB // alpha not used

             // you can choose what kind of blending mode you want for the outline
             Blend SrcAlpha OneMinusSrcAlpha // Normal
             //Blend One One // Additive
             //Blend One OneMinusDstColor // Soft Additive
             //Blend DstColor Zero // Multiplicative
             //Blend DstColor SrcColor // 2x Multiplicative

 CGPROGRAM
 #pragma vertex vert
 #pragma fragment frag

 half4 frag(v2f i) :COLOR {
     return i.color;
 }
 ENDCG
         }

         Pass {
             Name "BASE"
             ZWrite On
             ZTest LEqual
             Blend SrcAlpha OneMinusSrcAlpha
             Material {
                 Diffuse [_Color]
                 Ambient [_Color]
             }
             Lighting On
             SetTexture [_MainTex] {
                 ConstantColor [_Color]
                 Combine texture * constant
             }
             SetTexture [_MainTex] {
                 Combine previous * primary DOUBLE
             }
         }
     }

     SubShader {
         Tags { "Queue" = "Transparent" }

         Pass {
             Name "OUTLINE"
             Tags { "LightMode" = "Always" }
             Cull Front
             ZWrite Off
             ZTest Always
             ColorMask RGB

             // you can choose what kind of blending mode you want for the outline
             Blend SrcAlpha OneMinusSrcAlpha // Normal
             //Blend One One // Additive
             //Blend One OneMinusDstColor // Soft Additive
             //Blend DstColor Zero // Multiplicative
             //Blend DstColor SrcColor // 2x Multiplicative

             CGPROGRAM
             #pragma vertex vert
             #pragma exclude_renderers gles xbox360 ps3
             ENDCG
             SetTexture [_MainTex] { combine primary }
         }

         Pass {
             Name "BASE"
             ZWrite On
             ZTest LEqual
             Blend SrcAlpha OneMinusSrcAlpha
             Material {
                 Diffuse [_Color]
                 Ambient [_Color]
             }
             Lighting On
             SetTexture [_MainTex] {
                 ConstantColor [_Color]
                 Combine texture * constant
             }
             SetTexture [_MainTex] {
                 Combine previous * primary DOUBLE
             }
         }
     }

     Fallback "Diffuse"
 }

在将着色器附加到立方体上的 material 之后,我现在想在 csharp 脚本中控制轮廓宽度,所以我现在还附加了一个空的脚本到立方体:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Outline : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}

例如我想使用时间或 startcoroutine 更改轮廓宽度值。

如果轮廓宽度范围值为 0.0、0.03,那么我想使用时间或 startcoroutine 将此值从 0 自动更改为 0.03。

更新:

这正在使用更新来更改 _Outline 值:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Outline : MonoBehaviour
{
    public float width;

    private Renderer rend;
    private float currentWidth;

    private void Start()
    {
        rend = GetComponent<Renderer>();
        currentWidth = rend.material.GetFloat("_Outline");
    }

    private void Update()
    {
        SetOutLineWidth(width);
    }

    public void SetOutLineWidth(float width)
    {
        rend.material.SetFloat("_Outline", width);
    }
}

但现在如何使用 startcoroutine 自动不间断地从 0.0 更改 _Outline 值到 0.03,然后从 0.03 更改回 0.0?

你有两个选择。

  1. 最简单的:将您的振荡值存储在脚本中(修改,然后使用新值调用 material.SetFloat())。

  2. Material.GetFloat()

不确定您是否仍然需要它,但这是我的解决方案,唯一不同的是宽度轮廓的变量名称

using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class BlinkingHighlight : MonoBehaviour {

        public Renderer rend;

        float initialWidth = 0f;
        float EndWidth = 0.025f;

        float waitTime = 0.5f;

        public bool TestBlinking = false;
        bool BlinkingCycleComplete = false;

        void Start() {
            rend = GetComponent<Renderer> ();
        }

        public IEnumerator Blinking(){
            //Debug.Log ("Blinking");
            BlinkingCycleComplete = true;
            rend.material.SetFloat ("_OutlineWidth", initialWidth);
            yield return new WaitForSeconds(waitTime);
            rend.material.SetFloat ("_OutlineWidth", EndWidth);
            yield return new WaitForSeconds(waitTime);
            BlinkingCycleComplete = false;
        }

        void Update() {
            if (TestBlinking == true && BlinkingCycleComplete == false) {
                StartCoroutine (Blinking ());
            } else if (TestBlinking == false) {
                rend.material.SetFloat ("_OutlineWidth", initialWidth);
            }
        }
    }