UGUI教程之-自定义UGUI 扩展

[Unity][UGUI]UGUI-Extensions学习--下载安装包 下载 Unity的包。导入 Unity 的项目工程参考资料:1.UnityUIExtensions Unity-UI-Extensions2.UGUI 扩展集3.(二十五)unity4.6学习Ugui中文文档-------UGUI-Extensions4.5. 阅读详情

UGUI中我们常用的控件比如Button、Label、ToggleGroup,往往我们会基于这些最基本的控件来实现我们的高级控件,那么本篇文章我们来学习下我们自定义的UGUI拓展控件。


1、UIButton 单独可使用


这个脚本可以 提供外部监听按下/点击/释放的3个事件(参数附带着数据)。  源官方Button只有 点击事件
using UnityEngine.Events;
using UnityEngine.EventSystems;
 
namespace UnityEngine.UI.Extensions
{
/// <summary>
/// UIButton
/// </summary>
[AddComponentMenu("UI/Extensions/UI Button")]
public class UIButton : Button, IPointerDownHandler, IPointerUpHandler
{
#region Sub-Classes
[System.Serializable]
public class UIButtonEvent : UnityEvent<PointerEventData.InputButton> { }
#endregion
 
#region Events
public UIButtonEvent OnButtonClick;
public UIButtonEvent OnButtonPress;
public UIButtonEvent OnButtonRelease;
#endregion
 
public override void OnPointerClick(PointerEventData eventData)
{
base.OnSubmit(eventData);
 
if (OnButtonClick != null)
{
OnButtonClick.Invoke(eventData.button);
}
}
void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
{
DoStateTransition(SelectionState.Pressed, false);
 
if (OnButtonPress != null)
{
OnButtonPress.Invoke(eventData.button);
}
}
void IPointerUpHandler.OnPointerUp(PointerEventData eventData)
{
DoStateTransition(SelectionState.Normal, false);
 
if (OnButtonRelease != null)
{
OnButtonRelease.Invoke(eventData.button);
}
}
}
}
2、UIFlippable  单独可使用


我需要一些时间现在翻转精灵和使用scale解决方案被证明是一个糟糕的主意,当使用布局网格等,所以试着写一个小脚本来翻转顶点相反。它目前做这份工作对我来说,我想分享它所以它在这儿……
这种翻转还有两种实现方式: 设置 Rotation x/y =>180,    Scale x/y =>-1;

using System.Collections.Generic;
 
namespace UnityEngine.UI.Extensions
{
[RequireComponent(typeof(RectTransform), typeof(Graphic)), DisallowMultipleComponent]
[AddComponentMenu("UI/Effects/Extensions/Flippable")]
public class UIFlippable : MonoBehaviour, IMeshModifier
{
[SerializeField] private bool m_Horizontal = false;
[SerializeField] private bool m_Veritical = false;
 
/// <summary>
/// 获取或设置一个值,该值指示是否应水平翻转
/// </summary>
/// <value><c>true</c> if horizontal; otherwise, <c>false</c>.</value>
public bool horizontal
{
get { return this.m_Horizontal; }
set { this.m_Horizontal = value; }
}
 
/// <summary>
/// 获取或设置一个值,该值指示是否应垂直翻转
/// </summary>
/// <value><c>true</c> if vertical; otherwise, <c>false</c>.</value>
public bool vertical
{
get { return this.m_Veritical; }
set { this.m_Veritical = value; }
}
 
protected void OnValidate()
{
this.GetComponent<Graphic>().SetVerticesDirty();
}
 
// 从mesh 得到 顶点集
public void ModifyMesh(/*List<UIVertex> verts*/ Mesh mesh)
{
List<UIVertex> verts = new List<UIVertex> ();
using (VertexHelper vertexHelper = new VertexHelper (mesh))
{
vertexHelper.GetUIVertexStream (verts);
}
 
RectTransform rt = this.transform as RectTransform;
 
for (int i = 0; i < verts.Count; ++i)
{
UIVertex v = verts[i];
 
// Modify positions
v.position = new Vector3(
(this.m_Horizontal ? (v.position.x + (rt.rect.center.x - v.position.x) * 2) : v.position.x),
(this.m_Veritical ?  (v.position.y + (rt.rect.center.y - v.position.y) * 2) : v.position.y),
v.position.z
);
 
// Apply
verts[i] = v;
}
 
// 在合成mesh
using (VertexHelper vertexHelper2 = new VertexHelper ())
{
vertexHelper2.AddUIVertexTriangleStream (verts);
vertexHelper2.FillMesh (mesh);
}
}
}
}
3、uGUITools   单独可使用


让你更了解 锚点、RectTransform等,   Editor脚本

using UnityEditor;
namespace UnityEngine.UI.Extensions
{
public class uGUITools : MonoBehaviour
{
[MenuItem("uGUI/Anchors to Corners %[")]
static void AnchorsToCorners()
{
foreach (Transform transform in Selection.transforms)
{
RectTransform t = transform as RectTransform;
RectTransform pt = Selection.activeTransform.parent as RectTransform;
 
if (t == null || pt == null) return;
 
Vector2 newAnchorsMin = new Vector2(t.anchorMin.x + t.offsetMin.x / pt.rect.width,
t.anchorMin.y + t.offsetMin.y / pt.rect.height);
Vector2 newAnchorsMax = new Vector2(t.anchorMax.x + t.offsetMax.x / pt.rect.width,
t.anchorMax.y + t.offsetMax.y / pt.rect.height);
 
t.anchorMin = newAnchorsMin;
t.anchorMax = newAnchorsMax;
t.offsetMin = t.offsetMax = new Vector2(0, 0);
}
}
 
[MenuItem("uGUI/Corners to Anchors %]")]
static void CornersToAnchors()
{
foreach (Transform transform in Selection.transforms)
{
RectTransform t = transform as RectTransform;
 
if (t == null) return;
 
t.offsetMin = t.offsetMax = new Vector2(0, 0);
}
}
 
[MenuItem("uGUI/Mirror Horizontally Around Anchors %;")]
static void MirrorHorizontallyAnchors()
{
MirrorHorizontally(false);
}
 
[MenuItem("uGUI/Mirror Horizontally Around Parent Center %:")]
static void MirrorHorizontallyParent()
{
MirrorHorizontally(true);
}
 
static void MirrorHorizontally(bool mirrorAnchors)
{
foreach (Transform transform in Selection.transforms)
{
RectTransform t = transform as RectTransform;
RectTransform pt = Selection.activeTransform.parent as RectTransform;
 
if (t == null || pt == null) return;
 
if (mirrorAnchors)
{
Vector2 oldAnchorMin = t.anchorMin;
t.anchorMin = new Vector2(1 - t.anchorMax.x, t.anchorMin.y);
t.anchorMax = new Vector2(1 - oldAnchorMin.x, t.anchorMax.y);
}
 
Vector2 oldOffsetMin = t.offsetMin;
t.offsetMin = new Vector2(-t.offsetMax.x, t.offsetMin.y);
t.offsetMax = new Vector2(-oldOffsetMin.x, t.offsetMax.y);
 
t.localScale = new Vector3(-t.localScale.x, t.localScale.y, t.localScale.z);
}
}
 
[MenuItem("uGUI/Mirror Vertically Around Anchors %'")]
static void MirrorVerticallyAnchors()
{
MirrorVertically(false);
}
 
[MenuItem("uGUI/Mirror Vertically Around Parent Center %\"")]
static void MirrorVerticallyParent()
{
MirrorVertically(true);
}
 
static void MirrorVertically(bool mirrorAnchors)
{
foreach (Transform transform in Selection.transforms)
{
RectTransform t = transform as RectTransform;
RectTransform pt = Selection.activeTransform.parent as RectTransform;
 
if (t == null || pt == null) return;
 
if (mirrorAnchors)
{
Vector2 oldAnchorMin = t.anchorMin;
t.anchorMin = new Vector2(t.anchorMin.x, 1 - t.anchorMax.y);
t.anchorMax = new Vector2(t.anchorMax.x, 1 - oldAnchorMin.y);
}
 
Vector2 oldOffsetMin = t.offsetMin;
t.offsetMin = new Vector2(t.offsetMin.x, -t.offsetMax.y);
t.offsetMax = new Vector2(t.offsetMax.x, -oldOffsetMin.y);
 
t.localScale = new Vector3(t.localScale.x, -t.localScale.y, t.localScale.z);
}
}
}
}
本篇UGUI教程关于UGUI的拓展介绍到此结束,下篇我们来学习ToolTip 、ReturnKeyTriggersButton、NicerOutline等

4、ToolTip 



【需要外部调用函数显示和隐藏内容】请注意–目前情况下仅适用于Screenspace Camera的画布设置,要包括Screenspace and Worldspace需要更新
namespace UnityEngine.UI.Extensions
{
[RequireComponent(typeof(RectTransform))]
[AddComponentMenu("UI/Extensions/Tooltip")]
public class ToolTip : MonoBehaviour
{
//text of the tooltip
private Text _text;
private RectTransform _rectTransform;
 
//if the tooltip is inside a UI element
private bool _inside;
 
private bool _xShifted, _yShifted = false;
 
private float width, height, canvasWidth, canvasHeight;
 
private int screenWidth, screenHeight;
 
private float YShift,xShift;
 
private RenderMode _guiMode;
 
private Camera _guiCamera;
 
// Use this for initialization
public void Awake()
{
var _canvas = GetComponentInParent<Canvas>();
_guiCamera = _canvas.worldCamera;
_guiMode = _canvas.renderMode;
_rectTransform = GetComponent<RectTransform>();
 
_text = GetComponentInChildren<Text>();
 
_inside = false;
 
//size of the screen
screenWidth = Screen.width;
screenHeight = Screen.height;
 
xShift = 0f;
YShift = -30f;
 
_xShifted = _yShifted = false;
this.gameObject.SetActive(false);
 
}
 
//Call this function externally to set the text of the template and activate the tooltip
public void SetTooltip(string ttext)
{
 
if (_guiMode == RenderMode.ScreenSpaceCamera)
{
//set the text and fit the tooltip panel to the text size
_text.text = ttext;
 
_rectTransform.sizeDelta = new Vector2(_text.preferredWidth + 40f, _text.preferredHeight + 25f);
 
OnScreenSpaceCamera();
 
}
}
 
//call this function on mouse exit to deactivate the template
public void HideTooltip()
{
if (_guiMode == RenderMode.ScreenSpaceCamera)
{
this.gameObject.SetActive(false);
_inside = false;
}
}
 
// Update is called once per frame
void FixedUpdate()
{
if (_inside)
{
if (_guiMode == RenderMode.ScreenSpaceCamera)
{
OnScreenSpaceCamera();
}
}
}
 
//main tooltip edge of screen guard and movement
public void OnScreenSpaceCamera()
{
Vector3 newPos = _guiCamera.ScreenToViewportPoint(Input.mousePosition - new Vector3(xShift, YShift, 0f));
Vector3 newPosWVP = _guiCamera.ViewportToWorldPoint(newPos);
 
width = _rectTransform.sizeDelta[0];
height = _rectTransform.sizeDelta[1];
 
// check and solve problems for the tooltip that goes out of the screen on the horizontal axis
float val;
 
Vector3 lowerLeft = _guiCamera.ViewportToWorldPoint(new Vector3(0.0f, 0.0f, 0.0f));
Vector3 upperRight = _guiCamera.ViewportToWorldPoint(new Vector3(1.0f, 1.0f, 0.0f));
 
//check for right edge of screen
val = (newPosWVP.x + width / 2);
if (val > upperRight.x)
{
Vector3 shifter = new Vector3(val - upperRight.x, 0f, 0f);
Vector3 newWorldPos = new Vector3(newPosWVP.x - shifter.x, newPos.y, 0f);
newPos.x = _guiCamera.WorldToViewportPoint(newWorldPos).x;
}
//check for left edge of screen
val = (newPosWVP.x - width / 2);
if (val < lowerLeft.x)
{
Vector3 shifter = new Vector3(lowerLeft.x - val, 0f, 0f);
Vector3 newWorldPos = new Vector3(newPosWVP.x + shifter.x, newPos.y, 0f);
newPos.x = _guiCamera.WorldToViewportPoint(newWorldPos).x;
}
 
// check and solve problems for the tooltip that goes out of the screen on the vertical axis
 
//check for upper edge of the screen
val = (newPosWVP.y + height / 2);
if (val > upperRight.y)
{
Vector3 shifter = new Vector3(0f, 35f + height / 2, 0f);
Vector3 newWorldPos = new Vector3(newPos.x, newPosWVP.y - shifter.y, 0f);
newPos.y = _guiCamera.WorldToViewportPoint(newWorldPos).y;
}
 
//check for lower edge of the screen (if the shifts of the tooltip are kept as in this code, no need for this as the tooltip always appears above the mouse bu default)
val = (newPosWVP.y - height / 2);
if (val < lowerLeft.y)
{
Vector3 shifter = new Vector3(0f, 35f + height / 2, 0f);
Vector3 newWorldPos = new Vector3(newPos.x, newPosWVP.y + shifter.y, 0f);
newPos.y = _guiCamera.WorldToViewportPoint(newWorldPos).y;
}
 
this.transform.position = new Vector3(newPosWVP.x, newPosWVP.y, 0f);
this.gameObject.SetActive(true);
_inside = true;
}
}
}
5、ReturnKeyTriggersButton 


首先肯定是要配合 InputField 组件使用,是处理回车键, 【刚刚试了试 InputField 组件 很强大的哦】

using UnityEngine.EventSystems;
namespace UnityEngine.UI
{
[RequireComponent(typeof(InputField))]
[AddComponentMenu("UI/Extensions/Return Key Trigger")]
public class ReturnKeyTriggersButton : MonoBehaviour, ISubmitHandler
{
private EventSystem _system;
 
public Button button;
private bool highlight = true;
public float highlightDuration = 0.2f;
 
void Start()
{
_system = EventSystem.current;
}
 
void RemoveHighlight()
{
button.OnPointerExit(new PointerEventData(_system));
}
 
public void OnSubmit(BaseEventData eventData)
{
if (highlight) button.OnPointerEnter(new PointerEventData(_system));
button.OnPointerClick(new PointerEventData(_system));
 
if (highlight) Invoke("RemoveHighlight", highlightDuration);
}
}
}
6、NicerOutline 


和系统的 Outline效果上没有区别,但是实现方式不同可以好好研究一下


using System.Collections.Generic;
namespace UnityEngine.UI.Extensions
{
//An outline that looks a bit nicer than the default one. It has less "holes" in the outline by drawing more copies of the effect
[AddComponentMenu("UI/Effects/Extensions/Nicer Outline")]
public class NicerOutline : BaseMeshEffect
{
[SerializeField]
private Color m_EffectColor = new Color (0f, 0f, 0f, 0.5f);
 
[SerializeField]
private Vector2 m_EffectDistance = new Vector2 (1f, -1f);
 
[SerializeField]
private bool m_UseGraphicAlpha = true;
//
// Properties
//
public Color effectColor
{
get
{
return this.m_EffectColor;
}
set
{
this.m_EffectColor = value;
if (base.graphic != null)
{
base.graphic.SetVerticesDirty ();
}
}
}
 
public Vector2 effectDistance
{
get
{
return this.m_EffectDistance;
}
set
{
if (value.x > 600f)
{
value.x = 600f;
}
if (value.x < -600f)
{
value.x = -600f;
}
if (value.y > 600f)
{
value.y = 600f;
}
if (value.y < -600f)
{
value.y = -600f;
}
if (this.m_EffectDistance == value)
{
return;
}
this.m_EffectDistance = value;
if (base.graphic != null)
{
base.graphic.SetVerticesDirty ();
}
}
}
 
public bool useGraphicAlpha
{
get
{
return this.m_UseGraphicAlpha;
}
set
{
this.m_UseGraphicAlpha = value;
if (base.graphic != null)
{
base.graphic.SetVerticesDirty ();
}
}
}
//
// Methods
//
protected void ApplyShadow (List<UIVertex> verts, Color32 color, int start, int end, float x, float y)
{
//Debug.Log("verts count: "+verts.Count);
int num = verts.Count * 2;
if (verts.Capacity < num)
{
verts.Capacity = num;
}
for (int i = start; i < end; i++)
{
UIVertex uIVertex = verts [i];
verts.Add (uIVertex);
 
Vector3 position = uIVertex.position;
//Debug.Log("vertex pos: "+position);
position.x += x;
position.y += y;
uIVertex.position = position;
Color32 color2 = color;
if (this.m_UseGraphicAlpha)
{
color2.a = (byte)(color2.a * verts [i].color.a / 255);
}
uIVertex.color = color2;
//uIVertex.color = (Color32)Color.blue;
verts [i] = uIVertex;
}
}
 
public override void ModifyMesh (/*List<UIVertex> verts*/ Mesh mesh)
{
if (!this.IsActive ())
{
return;
}
// 从mesh 得到 顶点集
List<UIVertex> verts = new List<UIVertex> ();
using (VertexHelper vertexHelper = new VertexHelper (mesh))
{
vertexHelper.GetUIVertexStream (verts);
}
 
Text foundtext = GetComponent<Text>();
 
float best_fit_adjustment = 1f;
 
if (foundtext && foundtext.resizeTextForBestFit)
{
best_fit_adjustment = (float)foundtext.cachedTextGenerator.fontSizeUsedForBestFit / (foundtext.resizeTextMaxSize-1); //max size seems to be exclusive
 
}
 
float distanceX = this.effectDistance.x * best_fit_adjustment;
float distanceY = this.effectDistance.y * best_fit_adjustment;
 
int start = 0;
int count = verts.Count;
this.ApplyShadow (verts, this.effectColor, start, verts.Count, distanceX, distanceY);
start = count;
count = verts.Count;
this.ApplyShadow (verts, this.effectColor, start, verts.Count, distanceX, -distanceY);
start = count;
count = verts.Count;
this.ApplyShadow (verts, this.effectColor, start, verts.Count, -distanceX, distanceY);
start = count;
count = verts.Count;
this.ApplyShadow (verts, this.effectColor, start, verts.Count, -distanceX, -distanceY);
 
start = count;
count = verts.Count;
this.ApplyShadow (verts, this.effectColor, start, verts.Count, distanceX, 0);
start = count;
count = verts.Count;
this.ApplyShadow (verts, this.effectColor, start, verts.Count, -distanceX, 0);
 
start = count;
count = verts.Count;
this.ApplyShadow (verts, this.effectColor, start, verts.Count, 0, distanceY);
start = count;
count = verts.Count;
this.ApplyShadow (verts, this.effectColor, start, verts.Count, 0, -distanceY);
 
// 在合成mesh
using (VertexHelper vertexHelper2 = new VertexHelper ())
{
vertexHelper2.AddUIVertexTriangleStream (verts);
vertexHelper2.FillMesh (mesh);
}
}
 
protected override void OnValidate ()
{
this.effectDistance = this.m_EffectDistance;
base.OnValidate ();
}
}
}
7、LetterSpacing


单独使用 每个字符间可以设置间距了!【uGUI Text 组件支持行间距,但不是字符间距。 问题是-text layout 引擎不是开源的的一部分,你无法拿到合适的 API,一种解决办法是,只需修改现有的字体,每个字符添加额外的空间。这是那样难以管理,它的声音,和我到其中有很多的不同间隔标题工作不切实际的最近的设计。我需要为每个不同的间距不同的字体。    我最好的解决办法是,只需修改现有的字体fonts ,每个字符添加额外的空间。这样难以管理,我到其中有很多的不同间隔标题工作不切实际的设计。我需要为每个不同的间距不同的字体。     然后偶然看了看Shadow 效果,使用 BaseVertexEffect 来修改绘制的源对象的几何形状的顶点列表。和这个技术相同,文本 间距(虽然它不会产生任何额外的verts)。将组件添加到 UI 文本字段,调整间距值,完成工作。但它不能很好与rich text或自动换行的文本工作】

using System.Collections.Generic;
 
namespace UnityEngine.UI.Extensions
{
[AddComponentMenu("UI/Effects/Extensions/Letter Spacing")]
public class LetterSpacing : BaseMeshEffect
{
[SerializeField]
private float m_spacing = 0f;
 
protected LetterSpacing() { }
 
#if UNITY_EDITOR
protected override void OnValidate()
{
spacing = m_spacing;
base.OnValidate();
}
#endif
 
public float spacing
{
get { return m_spacing; }
set
{
if (m_spacing == value) return;
m_spacing = value;
if (graphic != null) graphic.SetVerticesDirty();
}
}
 
public override void ModifyMesh(/*List<UIVertex> verts*/Mesh mesh)
{
if (! IsActive()) return;
 
// 从mesh 得到 顶点集
List<UIVertex> verts = new List<UIVertex> ();
using (VertexHelper vertexHelper = new VertexHelper (mesh))
{
vertexHelper.GetUIVertexStream (verts);
}
 
Text text = GetComponent<Text>();
if (text == null)
{
Debug.LogWarning("LetterSpacing: Missing Text component");
return;
}
 
string[] lines = text.text.Split('\n');
Vector3  pos;
float    letterOffset    = spacing * (float)text.fontSize / 100f;
float    alignmentFactor = 0;
int      glyphIdx        = 0;
 
switch (text.alignment)
{
case TextAnchor.LowerLeft:
case TextAnchor.MiddleLeft:
case TextAnchor.UpperLeft:
alignmentFactor = 0f;
break;
 
case TextAnchor.LowerCenter:
case TextAnchor.MiddleCenter:
case TextAnchor.UpperCenter:
alignmentFactor = 0.5f;
break;
 
case TextAnchor.LowerRight:
case TextAnchor.MiddleRight:
case TextAnchor.UpperRight:
alignmentFactor = 1f;
break;
}
 
for (int lineIdx=0; lineIdx < lines.Length; lineIdx++)
{
string line = lines[lineIdx];
float lineOffset = (line.Length -1) * letterOffset * alignmentFactor;
 
for (int charIdx = 0; charIdx < line.Length; charIdx++)
{
int idx1 = glyphIdx * 4 + 0;
int idx2 = glyphIdx * 4 + 1;
int idx3 = glyphIdx * 4 + 2;
int idx4 = glyphIdx * 4 + 3;
 
// Check for truncated text (doesn't generate verts for all characters)
if (idx4 > verts.Count - 1) return;
 
UIVertex vert1 = verts[idx1];
UIVertex vert2 = verts[idx2];
UIVertex vert3 = verts[idx3];
UIVertex vert4 = verts[idx4];
 
pos = Vector3.right * (letterOffset * charIdx - lineOffset);
 
vert1.position += pos;
vert2.position += pos;
vert3.position += pos;
vert4.position += pos;
 
verts[idx1] = vert1;
verts[idx2] = vert2;
verts[idx3] = vert3;
verts[idx4] = vert4;
 
glyphIdx++;
}
 
// Offset for carriage return character that still generates verts
glyphIdx++;
}
 
// 在合成mesh
using (VertexHelper vertexHelper2 = new VertexHelper ())
{
vertexHelper2.AddUIVertexTriangleStream (verts);
vertexHelper2.FillMesh (mesh);
}
}
}
}

本篇UGUI教程关于UGUI的拓展介绍到此结束,下篇我们来学习 Gradient  、UIWindowBase 、lowLayoutGroup 等


8、Gradient 

和之前发表的blog差不多吧,这个是可以对Text文本内容的而且有global/local模式,选项更多了【可以研究源码】

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
using System.Collections.Generic;
 
namespace UnityEngine.UI.Extensions
{
// [RequireComponent(typeof(Text), typeof(RectTransform))]
[AddComponentMenu( "UI/Effects/Extensions/Gradient" )]
public class Gradient : BaseMeshEffect
{
public GradientMode gradientMode = GradientMode.Global;
public GradientDir gradientDir = GradientDir.Vertical;
public bool overwriteAllColor = false ;
public Color vertex1 = Color.white;
public Color vertex2 = Color.black;
private Graphic targetGraphic;
 
protected override void Start()
{
targetGraphic = GetComponent<Graphic>();
}
 
public override void ModifyMesh( /*List<UIVertex> vertexList*/ Mesh mesh)
{
// 从mesh 得到 顶点集
List<UIVertex> vertexList = new List<UIVertex> ();
using (VertexHelper vertexHelper = new VertexHelper (mesh))
{
vertexHelper.GetUIVertexStream (vertexList);
}
 
if (!IsActive() || vertexList.Count == 0)
{
return ;
}
int count = vertexList.Count;
UIVertex uiVertex = vertexList[0];
if (gradientMode == GradientMode.Global)
{
if (gradientDir == GradientDir.DiagonalLeftToRight || gradientDir == GradientDir.DiagonalRightToLeft)
{
#if UNITY_EDITOR
Debug.LogWarning( "Diagonal dir is not supported in Global mode" );
#endif
gradientDir = GradientDir.Vertical;
}
float bottomY = gradientDir == GradientDir.Vertical ? vertexList[vertexList.Count - 1].position.y : vertexList[vertexList.Count - 1].position.x;
float topY = gradientDir == GradientDir.Vertical ? vertexList[0].position.y : vertexList[0].position.x;
 
float uiElementHeight = topY - bottomY;
 
for ( int i = 0; i < count; i++)
{
uiVertex = vertexList[i];
if (!overwriteAllColor && uiVertex.color != targetGraphic.color)
continue ;
uiVertex.color *= Color.Lerp(vertex2, vertex1, ((gradientDir == GradientDir.Vertical ? uiVertex.position.y : uiVertex.position.x) - bottomY) / uiElementHeight);
vertexList[i] = uiVertex;
}
}
else
{
for ( int i = 0; i < count; i++)
{
uiVertex = vertexList[i];
if (!overwriteAllColor && !CompareCarefully(uiVertex.color, targetGraphic.color))
continue ;
switch (gradientDir)
{
case GradientDir.Vertical:
uiVertex.color *= (i % 4 == 0 || (i - 1) % 4 == 0) ? vertex1 : vertex2;
break ;
case GradientDir.Horizontal:
uiVertex.color *= (i % 4 == 0 || (i - 3) % 4 == 0) ? vertex1 : vertex2;
break ;
case GradientDir.DiagonalLeftToRight:
uiVertex.color *= (i % 4 == 0) ? vertex1 : ((i - 2) % 4 == 0 ? vertex2 : Color.Lerp(vertex2, vertex1, 0.5f));
break ;
case GradientDir.DiagonalRightToLeft:
uiVertex.color *= ((i - 1) % 4 == 0) ? vertex1 : ((i - 3) % 4 == 0 ? vertex2 : Color.Lerp(vertex2, vertex1, 0.5f));
break ;
 
}
vertexList[i] = uiVertex;
}
}
 
// 在合成mesh
using (VertexHelper vertexHelper2 = new VertexHelper ())
{
vertexHelper2.AddUIVertexTriangleStream (vertexList);
vertexHelper2.FillMesh (mesh);
}
}
private bool CompareCarefully(Color col1, Color col2)
{
if (Mathf.Abs(col1.r - col2.r) < 0.003f && Mathf.Abs(col1.g - col2.g) < 0.003f && Mathf.Abs(col1.b - col2.b) < 0.003f && Mathf.Abs(col1.a - col2.a) < 0.003f)
return true ;
return false ;
}
}
 
public enum GradientMode
{
Global,
Local
}
 
public enum GradientDir
{
Vertical,
Horizontal,
DiagonalLeftToRight,
DiagonalRightToLeft
//Free
}
//enum color mode Additive, Multiply, Overwrite
}

9、UIWindowBase

挂上之后, 可以拖动UI元素

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using System;
using UnityEngine.EventSystems;
 
namespace UnityEngine.UI.Extensions
{
/// <summary>
/// Includes a few fixes of my own, mainly to tidy up duplicates, remove unneeded stuff and testing. (nothing major, all the crew above did the hard work!)
/// </summary>
[RequireComponent(typeof(RectTransform))]
[AddComponentMenu( "UI/Extensions/UI Window Base" )]
public class UIWindowBase : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
RectTransform m_transform = null;
private bool _isDragging = false ;
public static bool ResetCoords = false ;
private Vector3 m_originalCoods = Vector3.zero;
private Canvas m_canvas;
private RectTransform m_canvasRectTransform;
public int KeepWindowInCanvas = 5;            // # of pixels of the window that must stay inside the canvas view.
 
// Use this for initialization
void Start()
{
m_transform = GetComponent<RectTransform>();
m_originalCoods = m_transform.position;
m_canvas = GetComponentInParent<Canvas>();
m_canvasRectTransform = m_canvas.GetComponent<RectTransform>();
}
 
void Update()
{
if (ResetCoords)
resetCoordinatePosition();
}
 
public void OnDrag(PointerEventData eventData)
{
if (_isDragging)
{
var delta = ScreenToCanvas(eventData.position) - ScreenToCanvas(eventData.position - eventData.delta);
m_transform.localPosition += delta;
}
}
 
//Note, the begin drag and end drag aren't actually needed to control the drag.  However, I'd recommend keeping it in case you want to do somethind else when draggging starts and stops
public void OnBeginDrag(PointerEventData eventData)
{
 
if (eventData.pointerCurrentRaycast.gameObject == null)
return ;
 
if (eventData.pointerCurrentRaycast.gameObject.name == name)
{
_isDragging = true ;
}
}
 
public void OnEndDrag(PointerEventData eventData)
{
_isDragging = false ;
}
 
void resetCoordinatePosition()
{
m_transform.position = m_originalCoods;
ResetCoords = false ;
}
 
private Vector3 ScreenToCanvas(Vector3 screenPosition)
{
Vector3 localPosition;
Vector2 min;
Vector2 max;
var canvasSize = m_canvasRectTransform.sizeDelta;
 
if (m_canvas.renderMode == RenderMode.ScreenSpaceOverlay || (m_canvas.renderMode == RenderMode.ScreenSpaceCamera && m_canvas.worldCamera == null))
{
localPosition = screenPosition;
 
min = Vector2.zero;
max = canvasSize;
}
else
{
var ray = m_canvas.worldCamera.ScreenPointToRay(screenPosition);
var plane = new Plane(m_canvasRectTransform.forward, m_canvasRectTransform.position);
 
float distance;
if (plane.Raycast(ray, out distance) == false )
{
throw new Exception( "Is it practically possible?" );
};
var worldPosition = ray.origin + ray.direction * distance;
localPosition = m_canvasRectTransform.InverseTransformPoint(worldPosition);
 
min = -Vector2.Scale(canvasSize, m_canvasRectTransform.pivot);
max = Vector2.Scale(canvasSize, Vector2.one - m_canvasRectTransform.pivot);
}
 
// keep window inside canvas
localPosition.x = Mathf.Clamp(localPosition.x, min.x + KeepWindowInCanvas, max.x - KeepWindowInCanvas);
localPosition.y = Mathf.Clamp(localPosition.y, min.y + KeepWindowInCanvas, max.y - KeepWindowInCanvas);
 
return localPosition;
}
}
}

10、FlowLayoutGroup      一种布局组件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
using System.Collections.Generic;
 
namespace UnityEngine.UI.Extensions
{
/// <summary>
/// Layout Group controller that arranges children in rows, fitting as many on a line until total width exceeds parent bounds
/// </summary>
[AddComponentMenu( "Layout/Extensions/Flow Layout Group" )]
public class FlowLayoutGroup : LayoutGroup
{
public float Spacing = 0f;
 
public bool ChildForceExpandWidth = false ;
public bool ChildForceExpandHeight = false ;
 
private float _layoutHeight;
 
public override void CalculateLayoutInputHorizontal()
{
 
base.CalculateLayoutInputHorizontal();
 
var minWidth = GetGreatestMinimumChildWidth() + padding.left + padding.right;
 
SetLayoutInputForAxis(minWidth, -1, -1, 0);
 
}
 
public override void SetLayoutHorizontal()
{
SetLayout(rectTransform.rect.width, 0, false );
}
 
public override void SetLayoutVertical()
{
SetLayout(rectTransform.rect.width, 1, false );
}
 
public override void CalculateLayoutInputVertical()
{
_layoutHeight = SetLayout(rectTransform.rect.width, 1, true );
}
 
protected bool IsCenterAlign
{
get
{
return childAlignment == TextAnchor.LowerCenter || childAlignment == TextAnchor.MiddleCenter ||
childAlignment == TextAnchor.UpperCenter;
}
}
 
protected bool IsRightAlign
{
get
{
return childAlignment == TextAnchor.LowerRight || childAlignment == TextAnchor.MiddleRight ||
childAlignment == TextAnchor.UpperRight;
}
}
 
protected bool IsMiddleAlign
{
get
{
return childAlignment == TextAnchor.MiddleLeft || childAlignment == TextAnchor.MiddleRight ||
childAlignment == TextAnchor.MiddleCenter;
}
}
 
protected bool IsLowerAlign
{
get
{
return childAlignment == TextAnchor.LowerLeft || childAlignment == TextAnchor.LowerRight ||
childAlignment == TextAnchor.LowerCenter;
}
}
 
/// <summary>
/// Holds the rects that will make up the current row being processed
/// </summary>
private readonly IList<RectTransform> _rowList = new List<RectTransform>();
 
/// <summary>
/// Main layout method
/// </summary>
/// <param name="width">Width to calculate the layout with</param>
/// <param name="axis">0 for horizontal axis, 1 for vertical</param>
/// <param name="layoutInput">If true, sets the layout input for the axis. If false, sets child position for axis</param>
public float SetLayout( float width, int axis, bool layoutInput)
{
var groupHeight = rectTransform.rect.height;
 
// Width that is available after padding is subtracted
var workingWidth = rectTransform.rect.width - padding.left - padding.right;
 
// Accumulates the total height of the rows, including spacing and padding.
var yOffset = IsLowerAlign ? ( float )padding.bottom : ( float )padding.top;
 
var currentRowWidth = 0f;
var currentRowHeight = 0f;
 
for (var i = 0; i < rectChildren.Count; i++) {
 
// LowerAlign works from back to front
var index = IsLowerAlign ? rectChildren.Count - 1 - i : i;
 
var child = rectChildren[index];
 
var childWidth = LayoutUtility.GetPreferredSize(child, 0);
var childHeight = LayoutUtility.GetPreferredSize(child, 1);
 
// Max child width is layout group with - padding
childWidth = Mathf.Min(childWidth, workingWidth);
 
// If adding this element would exceed the bounds of the row,
// go to a new line after processing the current row
if (currentRowWidth + childWidth > workingWidth) {
 
currentRowWidth -= Spacing;
 
// Process current row elements positioning
if (!layoutInput) {
 
var h = CalculateRowVerticalOffset(groupHeight, yOffset, currentRowHeight);
LayoutRow(_rowList, currentRowWidth, currentRowHeight, workingWidth, padding.left, h, axis);
 
}
 
// Clear existing row
_rowList.Clear();
 
// Add the current row height to total height accumulator, and reset to 0 for the next row
yOffset += currentRowHeight;
yOffset += Spacing;
 
currentRowHeight = 0;
currentRowWidth = 0;
 
}
 
currentRowWidth += childWidth;
_rowList.Add(child);
 
// We need the largest element height to determine the starting position of the next line
if (childHeight > currentRowHeight) {
currentRowHeight = childHeight;
}
 
currentRowWidth += Spacing;
}
 
if (!layoutInput) {
var h = CalculateRowVerticalOffset(groupHeight, yOffset, currentRowHeight);
 
// Layout the final row
LayoutRow(_rowList, currentRowWidth, currentRowHeight, workingWidth, padding.left, h, axis);
}
 
_rowList.Clear();
 
// Add the last rows height to the height accumulator
yOffset += currentRowHeight;
yOffset += IsLowerAlign ? padding.top : padding.bottom;
 
if (layoutInput) {
 
if (axis == 1)
SetLayoutInputForAxis(yOffset, yOffset, -1, axis);
 
}
 
return yOffset;
}
 
private float CalculateRowVerticalOffset( float groupHeight, float yOffset, float currentRowHeight)
{
float h;
 
if (IsLowerAlign) {
h = groupHeight - yOffset - currentRowHeight;
} else if (IsMiddleAlign) {
h = groupHeight*0.5f - _layoutHeight * 0.5f + yOffset;
} else {
h = yOffset;
}
return h;
}
 
protected void LayoutRow(IList<RectTransform> contents, float rowWidth, float rowHeight, float maxWidth, float xOffset, float yOffset, int axis)
{
var xPos = xOffset;
 
if (!ChildForceExpandWidth && IsCenterAlign)
xPos += (maxWidth - rowWidth) * 0.5f;
else if (!ChildForceExpandWidth && IsRightAlign)
xPos += (maxWidth - rowWidth);
 
var extraWidth = 0f;
 
if (ChildForceExpandWidth) {
extraWidth = (maxWidth - rowWidth)/_rowList.Count;
}
 
for (var j = 0; j < _rowList.Count; j++) {
 
var index = IsLowerAlign ? _rowList.Count - 1 - j : j;
 
var rowChild = _rowList[index];
 
var rowChildWidth = LayoutUtility.GetPreferredSize(rowChild, 0) + extraWidth;
var rowChildHeight = LayoutUtility.GetPreferredSize(rowChild, 1);
 
if (ChildForceExpandHeight)
rowChildHeight = rowHeight;
 
rowChildWidth = Mathf.Min(rowChildWidth, maxWidth);
 
var yPos = yOffset;
 
if (IsMiddleAlign)
yPos += (rowHeight - rowChildHeight) * 0.5f;
else if (IsLowerAlign)
yPos += (rowHeight - rowChildHeight);
 
if (axis == 0)
SetChildAlongAxis(rowChild, 0, xPos, rowChildWidth);
else
SetChildAlongAxis(rowChild, 1, yPos, rowChildHeight);
 
xPos += rowChildWidth + Spacing;
}
}
 
public float GetGreatestMinimumChildWidth()
{
var max = 0f;
 
for (var i = 0; i < rectChildren.Count; i++) {
var w = LayoutUtility.GetMinWidth(rectChildren[i]);
 
max = Mathf.Max(w, max);
}
 
return max;
}
}
}

11、CurvedText 

让文本按照曲线进行显示

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
using System.Collections.Generic;
 
namespace UnityEngine.UI.Extensions
{
/// <summary>
/// Curved text.让文本按照曲线进行显示 【注意对Image的变形 也是可以的】
/// 说明: 对Text的操作就和 shadow 和 outline 组件类似。
/// </summary>
// [RequireComponent(typeof(Text), typeof(RectTransform))]
[AddComponentMenu( "UI/Effects/Extensions/Curved Text" )]
public class CurvedText : BaseMeshEffect
{
// 曲线类型
public AnimationCurve curveForText = AnimationCurve.Linear(0, 0, 1, 10);
// 曲线程度
public float curveMultiplier = 1;
private RectTransform rectTrans;
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
if (curveForText[0]. time != 0)
{
var tmpRect = curveForText[0];
tmpRect. time = 0;
curveForText.MoveKey(0, tmpRect);
}
if (rectTrans == null)
rectTrans = GetComponent<RectTransform>();
if (curveForText[curveForText.length - 1]. time != rectTrans.rect.width)
OnRectTransformDimensionsChange();
}
#endif
protected override void Awake()
{
base.Awake();
rectTrans = GetComponent<RectTransform>();
OnRectTransformDimensionsChange();
}
protected override void OnEnable()
{
base.OnEnable();
rectTrans = GetComponent<RectTransform>();
OnRectTransformDimensionsChange();
}
/// <summary>
/// Modifies the mesh. 最重要的重载函数
/// </summary>
/// <param name="mesh">Mesh.</param>
public override void ModifyMesh( /*List<UIVertex> verts*/ Mesh mesh)
{
if (!IsActive())
return ;
 
// 从mesh 得到 顶点集
List<UIVertex> verts = new List<UIVertex> ();
using (VertexHelper vertexHelper = new VertexHelper (mesh))
{
vertexHelper.GetUIVertexStream (verts);
}
 
// 顶点的 y值按曲线变换
for ( int index = 0; index < verts.Count; index++)
{
var uiVertex = verts[index];
//Debug.Log ();
uiVertex.position.y += curveForText.Evaluate(rectTrans.rect.width * rectTrans.pivot.x + uiVertex.position.x) * curveMultiplier;
verts[index] = uiVertex;
}
 
// 在合成mesh
using (VertexHelper vertexHelper2 = new VertexHelper ())
{
vertexHelper2.AddUIVertexTriangleStream (verts);
vertexHelper2.FillMesh (mesh);
}
}
protected override void OnRectTransformDimensionsChange()
{
var tmpRect = curveForText[curveForText.length - 1];
tmpRect. time = rectTrans.rect.width;
curveForText.MoveKey(curveForText.length - 1, tmpRect);
}
}
}

本篇UGUI教程关于UGUI的拓展介绍到此结束,下篇我们来学习 CanvasGroupActivator、BestFitOutline   、AimerInputModule等


(二十五)unity4.6学习Ugui中文文档-------UGUI-Extensions 出处:http://blog.youkuaiyun.com/u010019717这个库是什么?在此存储库中是扩展脚本来增强您的Unity UI experience的集合。这些脚本从许多来源收集和合并,随着时间的推移改善Unity UI experience。(脚本绝大多数来自脚本线程上unity UI 论坛在这里)你可以下载/项目访问脚本,或您可以下载此预编译的 Unity Asset资产。Unity 阅读详情

相关推荐

Unity实现一个可扩展的UGUI无限滑动列表控件

采用对象池+存储布局坐标实现的一个基于UGUI的可横向或纵向的无限滑动列表。

. 6573

unity 原生UGUI代码扩展

unity的UGUI功能无疑是很强大 但是UGUI还是可以扩展的 我们可以继承UGUI原生的组件 实现扩展的效果 下面我扩展一下Toggle的功能 给大家举个例子 大家可以当做参考 上边这种方式 就是用扩展的Toggle实现的 下面我给出源码 其实特别简单 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngi

weixin_44302602的博客 1386

UGUI源码分析与研究3-扩展UGUI实现自定义UI组件

编写自定义UI组件的绘制代码:在脚本中,你可以重写Unity提供的OnGUI或者OnRectTransformDimensionsChange等方法,来实现自定义UI组件的绘制逻辑。创建自定义UI组件的脚本:首先,在Unity中创建一个新的C#脚本,用于定义你的自定义UI组件。在场景中使用自定义UI组件:将你的自定义UI组件脚本添加到场景中的一个UI元素上,或者通过代码动态创建并添加到场景中。实现自定义UI组件的功能:在脚本中,你可以添加需要的变量、方法和事件来实现你的自定义UI组件的功能。

谁为拨动染血的时空苍穹 635

UGUI 扩展集

孙广东   2015.8.10     基于Unity5.2版本1、UIButton 单独可使用        这个脚本可以 提供外部监听按下/点击/释放的3个事件(参数附带着数据)。  源官方Button只有 点击事件using UnityEngine.Events; using UnityEngine.EventSystems; namespace UnityEngine.UI.Extens

游戏路上的小学生 6961

Unity UGUI自定义无限循环滑动组件实战开发

自动居中功能是提升UI交互体验的重要手段之一。通过本章的详细分析,我们了解了自动居中的交互逻辑、核心算法实现以及Unity中的多种实现技巧。无论是通过手动编写插值逻辑,还是借助LeanTween、DOTween等工具库,都能实现平滑、自然的自动居中效果。此外,结合Unity的Input System,我们可以更精准地捕捉用户输入行为,从而实现更智能的自动居中判断和响应机制。下一章我们将继续深入,探讨如何实现无限制左右滚动功能,进一步扩展CustomSlider组件的能力。支持无限滚动。

weixin_42453228的博客 1266

unigui_调用外部js与css_左侧导航栏修正

unigui_调用外部js与css_左侧导航栏修正

UGUIExtend 开源项目教程

UGUIExtend 开源项目教程 项目介绍 UGUIExtend 是一个基于 Unity 的 UGUI 扩展库,旨在提供更多高级和定制化的 UI 组件,以满足复杂游戏界面的开发需求。该项目通过扩展 Unity 的 UGUI 系统,增加了许多实用的功能和组件,使得开发者能够更高效地创建复杂的用户界面。 项目快速启动 安装 克隆项目仓库到本地: git clone https://github....

gitblog_00032的博客 507

ESP32-CAM图像糊成马赛克?OV2640参数调优保姆级教程(亮度/对比度/饱和度)

本文提供了一份详细的ESP32-CAM图像调优教程,针对OV2640摄像头常见的图像模糊问题,从分辨率设置、亮度/对比度/饱和度调整到高级寄存器配置,帮助用户优化网页显示画质。通过代码示例和实用技巧,解决马赛克、色彩暗淡等问题,提升摄像头性能。

weixin_30410119的博客 595

uGUI-Hypertext 开源项目教程

uGUI-Hypertext 开源项目教程 1. 项目的目录结构及介绍 uGUI-Hypertext 项目的目录结构如下: uGUI-Hypertext/ ├── Assets/ │ ├── Scripts/ │ │ ├── Hypertext.cs │ │ └── HypertextGroup.cs │ └── Samples~ │ ├── SampleSce...

gitblog_00255的博客 263

STM32F103C8T6通过ESP8266连接阿里云物联网平台(附代码)

STM32F103C8T6连接阿里云物联网平台(1)—阿里云lot Studio控制 Web开发 分享一下自己使用stm32f103c8t6通过ESP_01模块连接阿里云物联网平台,实现温湿度上传和控制命令下达的过程,能力有限,用的是最简单的方法,如有错误,多多担待。 一、硬件选型 1、 stm32f103c8t6 2、ESP_01 wifi模块 3、其他 二、硬件连接 WSP_01 STM32F103C8T6 RXD PA2 TXD PA3 RES PA4 VCC 3.3

weixin_A13253323604 3万+

【OpenBMC 系列】4.启动流程 使用qume模拟ast2600-evb

1.安装openbmc适配的qume 2.启动bmc 3.使用bmc web

AiFool的博客 4459

Unity3D 重写下拉菜单/Dropdown组件、开启每个按钮可用

Override Dropdown Component 本文提供全流程,中文翻译。 Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) Chinar —— 心分享、心创新!为实现下拉菜单/...

weixin_34090562的博客 640

知识图谱_知识图谱 | 知识图谱做用户画像

导读:最近一直在思考怎么用知识图谱做推荐,但是目前能知道的内容都是基于路径的推荐和基于图特征的推荐,所以能不能换一个角度,探究一下用知识图谱怎么做用户画像,因为画像也是推荐系统重要的一部分。现在的知识图谱+推荐怎么做的传统的用户画像怎么做现在的知识图谱+推荐怎么做的?基于路径:可以理解成基于图谱的多路径召回,或者多路径推荐,然后根据路径的转移概率进行排序从而达到推荐的效果,基于路径比较适合简单的推...

weixin_28801659的博客 1460

终极Unity游戏翻译神器:XUnity.AutoTranslator完整使用教程

还在为外语游戏而烦恼吗?XUnity.AutoTranslator是专为Unity游戏打造的实时翻译插件,能够自动翻译游戏内的所有文本内容,让你轻松突破语言障碍,畅玩全球热门游戏!这款强大的工具支持多种游戏框架和翻译服务,无论是日文、英文还是其他语言,都能快速转换为中文,为你带来完美的本地化体验。 ## 🎮 为什么你需要这款翻译工具? **智能实时翻译** - 游戏运行过程中自动检测并翻译所

gitblog_01195的博客 377

【图像超分】论文精读:RepSR: Training Efficient VGG-style Super-Resolution Networks with Structural Re-Paramete

摘要: 本文提出RepSR,一种基于结构重新参数化和批量归一化(BN)的高效VGG式超分辨率网络。针对SR任务中BN易引发伪影的问题,作者通过分析发现训练-测试阶段的不一致性是主因,并提出先使用小批量统计训练、后期切换为总体统计的优化策略。RepSR块设计包含干净的残差路径和带改进BN的扩展-压缩卷积路径,有效平衡了训练非线性与推理效率。实验表明,RepSR在不同模型规模下优于现有重参数化方法,且实际推理速度更快。该工作为SR提供了性能与效率兼优的解决方案,相关代码未开源。 关键词: 超分辨率、结构重参数化

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 304

学Simulink--基础微电网场景实例:基于Simulink的微电网黑启动过程建模与仿真

黑启动(Black Start)是指在全系统停电(无电压、无频率)状态下,微电网依靠内部电源自主恢复供电的能力。🌩️典型场景主网长时间故障自然灾害导致区域停电计划检修后重启❗挑战无参考电压/频率 → 逆变器无法锁相负荷逐级投入 → 需避免过流/过压多电源协调 → 防止环流或失步✅黑启动成功标准在30 秒内恢复关键负荷供电电压/频率稳定在范围内无设备损坏或保护跳闸🎯本文目标:手把手教你使用 Simulink + Simscape + Stateflow 搭建。

amy_mhd的博客 201

unity UGUI Image之扩展

      由于ngui对新版的unity的兼容性越来越不好了,现在逐步转向unity的亲儿子---ugui。尝试着搭了几个ui之后,发现image的图片操作不是太方便(例如 我想在slice模式下,按照比例去放大图片),我每次都算一边。        用了ngui的我联想到能不能模仿者ngui UISprite的方式去扩展呢。哈哈,最终被我搞成了。先看效果         用过ngui的朋...

文刀雨田 1721

对雷达中相位补偿概念的一些理解

基于多普勒相位补偿的速度扩展方法和DBF测角,两者本质上都是对相位进行补偿。

qq_42235129的博客 4030

UGUI 扩展 —— 按钮声音组件

之前用NGUI的时候,里面有很多扩展功能很实用,但现在使用UGUI有很多功能需要自己扩展,以便项目使用,今天就简单介绍一下自己扩展的一个给按钮添加声音组件的功能,其实很简单直接上代码吧! using UnityEngine; using System.Collections; using UnityEngine.UI; public class PlayUIButtonSound : MonoBehaviour { public enum Trigger { OnClic

qq_36819905的博客 656

智能手表PCB布局:PPG与IMU传感器噪声隔离与应力解耦设计

在可穿戴设备硬件开发中,PCB布局已超越传统布线范畴,成为决定信号完整性、电磁兼容性与机械可靠性的核心环节。心率传感器(PPG)依赖微伏级光电容积脉搏波信号,极易受数字开关噪声与电源纹波干扰;姿态传感器(IMU)则对PCB弯曲形变引发的机械应力高度敏感。其布局需融合电磁场建模、热-力-电多物理协同及高密度互连约束。关键技术价值体现在噪声路径切断、地弹抑制、应力方向解耦与电源域隔离等工程实践。典型应用场景涵盖智能手表、医疗级贴片设备及微型运动传感终端。本文聚焦PPG与IMU两大模组在STM32L4平台上的实操

weixin_32869687的博客 173

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

unity ugui 图片 文本 大小完美自动扩展

    unity开发中总是会用到文本框大小自动扩展,图片和文本自动扩展,之前一直没有找到很好的解决方案,以至于用了很久自己计算的笨方法,一点都不方便;最近下定决心搞定他,本来想自己封装个较完善的方法,但是研究了UGUI后发现,unity已经帮我们做好了,只是一直不会用,汗颜。。。     下面我就来把我的理解说下,有不足的地方欢迎大家指出,一起学习进步。 一、自动扩展文本的大小     自动扩展文本大小比较简单,使用Content Size Fitter组件即可, Content Size Fitte

yunjianxi0000的博客 2523

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【UGUI扩展】扩展UGUI Button

源:https://github.com/yangyxd/YxdGameFrame/tree/master/YxdGameFrame/Assets/GameFrame/Frame/UGUI 这个UGUI button 扩展是基于这个项目整理的,斗胆以原创发布。 扩展后的效果: 可以通过这样的形式创建: 详细的完整代码如下: using System

赖张殷-Eagle 3823

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Unity UGUI扩展项目推荐

Unity UGUI扩展项目推荐 1. 项目基础介绍 Unity UGUI扩展项目是一个开源的Unity插件,它致力于扩展Unity内置的用户界面(UGUI)组件。该项目主要通过C#编程语言进行开发,为Unity开发者提供了更多的功能和组件,以优化和丰富用户界面设计。 2. 项目的核心功能 镜像图片制作:提供了一种优化方法,可以快速为UGUI组件生成镜像图片,这在设计对称界面时非常有用。 轮廓阴...

gitblog_00140的博客 426

【Unity】NGUI和UGUI比较

NGUI需要使用工具手动拼接图片成图集。UGUI开发期间可以直接使用图片作为元素,打包时会自动拼接成图集。图集的alpha拆分功能,NGUI可以通过增加工具类和shader来做,UGUI有自带的alpha拆分功能方便许多。组件支持功能比较。

希望有志同道合的的朋友可以互相学习! 6210

Unity UGUI Scroll View中文详解-Chinar

Chinar blog :www.chinar.xin Unity UGUI 完整系列教程 (Chinar中文图解) Unity UGUI-Scroll View 组件 本文提供全流程,中文翻译。 Chinar 的初衷是将一种简单的生活方式带给世人 使有限时间 具备无限可能 Chinar —— 心分享、心创新!助力快速掌握 Unity UGUI Scroll View组件的...

Chinar优快云的博客 1万+

Unity UGUI扩展

UI事件依赖于Graphic Raycast组件,必须绑在Canvas上,表示这个Canvas下所有UI元素支持的事件,如果不想这个Canvas下的UI不接收UI事件,可以关闭(enable=false)或者删除组件 UGUI的点击事件也基于射线,如果不需要响应事件,千万不要勾选RaycastTarget。UI事件会在EventSystem的Update方法中调用Process时触发。UGUI会遍历屏幕中所有Raycast是true的UI,接着就会发射线,并且排序找到玩家最先触发的那个UI,在抛出事件给逻辑

weixin_44806700的博客 853
上一篇: UGUI事件
下一篇: listview与adapter用法
appppppen
博客等级 码龄11年 13粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值