实现效果:
实现分析:这其实是一个四色角度渐变图像,加了一个角度值的关键帧动画,上图是一个边框贴图,下图是个实体贴图:
Unity实现:
思路:写一个四色角度渐变的shader,shader公开一个角度属性用于控制渐变角度,通过代码不停变换角度即可实现,下面给出详细的步骤,Unity版本:2021.3.23f1c1
1.新建一个shader文件,粘贴以下代码保存:
Shader "Custom/FourColorAngleGradient"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_Color0("Color 0", Color) = (1, 0, 0, 1)
_Color90("Color 90", Color) = (0, 1, 0, 1)
_Color180("Color 180", Color) = (0, 0, 1, 1)
_Color270("Color 270", Color) = (1, 1, 0, 1)
_GradientAngle("Gradient Angle", Range(-180, 180)) = 0.0
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
LOD 100
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _Color0;
float4 _Color90;
float4 _Color180;
float4 _Color270;
float _GradientAngle;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
float4 frag(v2f i) : SV_Target
{
// Sample the texture
float4 texColor = tex2D(_MainTex, i.uv);
if (texColor.a == 0)
discard;
// Calculate angle
float2 coord = i.uv - 0.5; // Offset to center
coord.y *= -1; // Invert y for correct angle calculation
float angle = atan2(coord.y, coord.x) * (180.0 / 3.14159265);
angle += 180.0; // Offset to make angle positive
angle -= _GradientAngle; // Apply gradient angle offset
if (angle < 0) angle += 360.0;
if (angle >= 360) angle -= 360.0;
// Determine color based on angle
float4 color;
if (angle < 90)
{
color = lerp(_Color0, _Color90, angle / 90);
}
else if (angle < 180)
{
color = lerp(_Color90, _Color180, (angle - 90) / 90);
}
else if (angle < 270)
{
color = lerp(_Color180, _Color270, (angle - 180) / 90);
}
else
{
color = lerp(_Color270, _Color0, (angle - 270) / 90);
}
// Combine texture and gradient color
return color * texColor;
}
ENDCG
}
}
FallBack "Diffuse"
}
2.通过shader创建一个材质、并将材质主贴图设定为 “边框贴图”
① 通过shader创建材质:
② 准备一张类似这样的边框png贴图:
③ 贴图设定 ”Alpha is Transparency“
④ 将材质的贴图设置为边框png贴图
3.在UGUI中实现:
① 创建一个RawImage,将材质赋值给它
② 编写控制材质角度属性的代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class NewBehaviourScript : MonoBehaviour
{
private Material thisMat;//RawImage的Material
const string angleProName = "_GradientAngle";//材质角度属性的名字
[SerializeField] float speed = 7.2f;//每秒数值增量为:50 * speed,7.2为一圈每秒
// Start is called before the first frame update
void Start()
{
thisMat = GetComponent<RawImage>().material;
}
// Update is called once per frame
void FixedUpdate()
{
var nowValue = thisMat.GetFloat(angleProName);
if ((nowValue += speed) > 180)
{
nowValue = -180;
}
thisMat.SetFloat(angleProName, nowValue);
}
}
③ 代码挂载到RawImage上,运行场景即可
4.通过修改四种颜色,可实现不同种类的流水线条
↓↓↓↓↓↓
↓↓↓↓↓↓
总结:重点就是实现 “角度渐变shader” ,关于shader实现思路,其实博主也不太懂~ shader是由chatgpt生成的,会用它就行了哈哈
项目资源:Unity跑马灯(流水灯)效果资源-CSDN文库https://download.csdn.net/download/njiyue/88886999
———————————————————————————————
CocosCreator 3.8.1 实现:
1.新建一个着色器(Effect),粘贴以下代码保存:
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
CCEffect %{
techniques:
- passes:
- vert: sprite-vs:vert
frag: sprite-fs:frag
depthStencilState:
depthTest: false
depthWrite: false
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
blendDstAlpha: one_minus_src_alpha
rasterizerState:
cullMode: none
properties:
color0: { value: [1.0, 0.0, 0.0, 1.0], editor: { type: color } }
color90: { value: [0.0, 1.0, 0.0, 1.0], editor: { type: color } }
color180: { value: [0.0, 0.0, 1.0, 1.0], editor: { type: color } }
color270: { value: [1.0, 1.0, 0.0, 1.0], editor: { type: color } }
gradientAngle: { value: 0.0, editor: { type: number, range: [-180.0, 180.0] } }
alphaThreshold: { value: 0.5 }
}%
CCProgram sprite-vs %{
precision highp float;
#include <builtin/uniforms/cc-global>
#if USE_LOCAL
#include <builtin/uniforms/cc-local>
#endif
#if SAMPLE_FROM_RT
#include <common/common-define>
#endif
in vec3 a_position;
in vec2 a_texCoord;
in vec4 a_color;
out vec4 color;
out vec2 uv0;
vec4 vert() {
vec4 pos = vec4(a_position, 1);
#if USE_LOCAL
pos = cc_matWorld * pos;
#endif
#if USE_PIXEL_ALIGNMENT
pos = cc_matView * pos;
pos.xyz = floor(pos.xyz);
pos = cc_matProj * pos;
#else
pos = cc_matViewProj * pos;
#endif
uv0 = a_texCoord;
#if SAMPLE_FROM_RT
CC_HANDLE_RT_SAMPLE_FLIP(uv0);
#endif
color = a_color;
return pos;
}
}%
CCProgram sprite-fs %{
precision highp float;
#include <builtin/internal/embedded-alpha>
#include <builtin/internal/alpha-test>
in vec4 color;
#if USE_TEXTURE
in vec2 uv0;
#pragma builtin(local)
layout(set = 2, binding = 12)uniform sampler2D cc_spriteTexture;
#endif
uniform pro {
vec4 color0;
vec4 color90;
vec4 color180;
vec4 color270;
float gradientAngle;
};
vec4 frag() {
vec4 texColor = vec4(1, 1, 1, 1);
#if USE_TEXTURE
texColor *= CCSampleWithAlphaSeparated(cc_spriteTexture, uv0);
vec2 coord = uv0 - 0.5;
coord.y *= -1.0;
float angle = atan(coord.y, coord.x) * (180.0 / 3.14159265);
angle += 180.0;
angle -= gradientAngle;
if (angle < 0.0) angle += 360.0;
if (angle >= 360.0) angle -= 360.0;
vec4 color;
if (angle < 90.0) {
color = mix(color0, color90, angle / 90.0);
} else if (angle < 180.0) {
color = mix(color90, color180, (angle - 90.0) / 90.0);
} else if (angle < 270.0) {
color = mix(color180, color270, (angle - 180.0) / 90.0);
} else {
color = mix(color270, color0, (angle - 270.0) / 90.0);
}
return color * texColor;
// #if IS_GRAY
// float gray = 0.2126 * o.r + 0.7152 * o.g + 0.0722 * o.b;
// o.r = o.g = o.b = gray;
// #endif
#endif
//o *= color;
//ALPHA_TEST(texColor);
//return texColor;
}
}%
2.创建一个材质,设定着色器、设置参数,保存
3.使用2D对象 sprite 来实现:
① 创建一个sprite(精灵)对象,将 材质 和 准备好的 透明底 边框 贴图 放至对应属性上。
② 注意这里有个坑,边框贴图的 Packable 要 取消打勾 ,否则会导致uv显示不正确。 ③ 写一个脚本挂载到 sprit对象上即可 (与unity同样的shader逻辑,但在cocos上它的流动是逆时针的,所以加了一个isForward属性控制转动方向),脚本内容:
import { _decorator, color, Component, Material, Node, Sprite } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('NewComponent')
export class NewComponent extends Component {
private mat: Material;
private readonly angleProName = "gradientAngle";//材质角度属性的名字
@property private speed = 360;///每秒一圈(360度)
@property private isForward = true;//是否为正向(顺时针)
start() {
this.mat = this.getComponent(Sprite).material;
}
update(deltaTime: number) {
let nowValue = this.mat.getProperty(this.angleProName) as number;
if (this.isForward) {
if ((nowValue -= this.speed * deltaTime) < -180) {
nowValue = 180;
}
}
else
if ((nowValue += this.speed * deltaTime) > 180) {
nowValue = -180;
}
this.mat.setProperty(this.angleProName, nowValue);
}
}
4. 实现效果:
项目资源:CocosCreator3.8.1跑马灯(流水灯)效果资源-CSDN文库https://download.csdn.net/download/njiyue/88899587