Unity 中画线

news2025/1/23 7:26:53

前言:
 

  在Unity项目中,调试和可视化是开发过程中不可或缺的部分。其中,绘制线条是一种常见的手段,可以用于在Scene场景和Game视图中进行调试和展示。本篇博客将为你介绍多种不同的绘制线条方法,帮助你轻松应对各种调试和可视化需求。

一、Debug.DrawLine

Debug.DrawLine 是 Unity 提供的一种用于在 Scene 视图中绘制调试线条的方法。

start世界空间中线条起始点的位置。
end在世界空间中指向线条的终点。
color线条的颜色。
duration线条的可见长度。

在 Update/FixedUpdate/LateUpdate 中调用:

这个方法通常用于游戏运行时进行更新,在这些方法中调用 Debug.DrawLine 来在不同帧更新时绘制线条。

只在 Scene 窗口里显示:

Debug.DrawLine 绘制的线条只能在 Scene 窗口中显示。这限制了在 Game 窗口中实时查看线条。

不能设置材质:

使用 Debug.DrawLine 绘制的线条无法更改或设置材质,因为它们主要用于调试和临时可视化,不提供材质设置的选项。

1、绘制正方体

[ExecuteInEditMode]
public class MyComponent1 : MonoBehaviour
{
    public float size = 1; // 正方体的大小

    private Vector3[] vertices = new Vector3[8]
    {
        new Vector3(-1, -1, -1),
        new Vector3(1, -1, -1),
        new Vector3(1, -1, 1),
        new Vector3(-1, -1, 1),
        new Vector3(-1, 1, -1),
        new Vector3(1, 1, -1),
        new Vector3(1, 1, 1),
        new Vector3(-1, 1, 1),
    };


    private void Update()
    {
        for (int i = 0; i < 4; i++)
        {
            int next = (i < 3) ? (i + 1) : 0;
            // 底部边框线
            Debug.DrawLine(vertices[i] * size * 0.5f, vertices[next] * size * 0.5f, Color.green);
            // 顶部边框线
            Debug.DrawLine(vertices[i + 4] * size * 0.5f, vertices[next + 4] * size * 0.5f, Color.green);
            // 垂直边框线
            Debug.DrawLine(vertices[i] * size * 0.5f, vertices[i + 4] * size * 0.5f, Color.green); 
        }
    }
}

要使用 Debug.DrawLine 绘制一个正方体,需要考虑其边界上的顶点和线条之间的关系。下面是一个示例代码,用于在场景中绘制一个简单的正方体:

2、绘制网格

using UnityEngine;

public class DrawGrid : MonoBehaviour
{
    public float gridSize = 1.0f; // 网格单元的大小
    public int gridSizeX = 10; // 网格的列数
    public int gridSizeY = 10; // 网格的行数

    void OnDrawGizmos()
    {
        // 绘制水平方向的线条
        for (int i = 0; i <= gridSizeX; i++)
        {
            Vector3 start = Vector3.right * i * gridSize;
            Vector3 end = start + Vector3.forward * gridSize * gridSizeY;
            Debug.DrawLine(start, end, Color.white);
        }

        // 绘制垂直方向的线条
        for (int i = 0; i <= gridSizeY; i++)
        {
            Vector3 start = Vector3.forward * i * gridSize;
            Vector3 end = start + Vector3.right * gridSize * gridSizeX;
            Debug.DrawLine(start, end, Color.white);
        }
    }
}

使用 Debug.DrawLine 绘制一个 10x10 的网格。将这个脚本附加到一个空 GameObject 上。gridSize 变量表示网格的单元大小,gridSizeX 和 gridSizeY 分别表示网格的列数和行数。在 Scene 视图中,可以看到一个由绿色线条组成的网格。这些线条只是用于调试和可视化,不会在游戏中显示。

二、Gizmos.DrawLine

Gizmos.DrawLine 是 Unity 提供的一个用于在 Scene 窗口中绘制线条的函数。它可以在 OnDrawGizmos 和 OnDrawGizmosSelected 方法中使用。

from世界空间中线条起始点的位置。
to在世界空间中指向线条的终点。

调用方式:

适合在 OnDrawGizmos 和 OnDrawGizmosSelected 这两个 Unity 生命周期方法中调用。这些方法是专门用于在 Scene 窗口中绘制 Gizmo 的。

显示范围:

所绘制的线条只会在 Scene 窗口中显示,而不会出现在游戏运行中。这有助于在编辑器中进行调试和可视化,但不会影响游戏性能或最终的构建。

材质设置:

Gizmos 提供的绘制方法通常不能设置材质、颜色等属性。Gizmos.DrawLine 绘制的线条颜色和材质是固定的,无法调整其粗细、透明度或使用自定义材质。

1、绘制网格

using UnityEngine;

public class DrawGrid : MonoBehaviour
{
    public float gridSize = 1.0f; // 网格单元的大小
    public int gridSizeX = 10; // 网格的列数
    public int gridSizeY = 10; // 网格的行数

    void OnDrawGizmos()
    {
        Gizmos.color = Color.red;

        // 绘制水平方向的线条
        for (int i = 0; i <= gridSizeX; i++)
        {
            Vector3 start = Vector3.right * i * gridSize;
            Vector3 end = start + Vector3.forward * gridSize * gridSizeY;
            Gizmos.DrawLine(start, end);
        }

        // 绘制垂直方向的线条
        for (int i = 0; i <= gridSizeY; i++)
        {
            Vector3 start = Vector3.forward * i * gridSize;
            Vector3 end = start + Vector3.right * gridSize * gridSizeX;
            Gizmos.DrawLine(start, end);
        }
    }
}

在 OnDrawGizmos 方法中使用 Gizmos.DrawLine 绘制一个 10x10 的网格。这些线条只在 Scene 窗口中显示,并且不能设置材质。要注意的是,Gizmos 类用于在 Scene 窗口中绘制 Gizmo,但不会在游戏运行时显示。

三、Mesh

在Unity中,Mesh(网格)是一种用于表示3D模型的数据结构。它定义了一个网格模型的顶点、三角形(或其他多边形)、UV(纹理坐标)、法线(法线方向)等数据。Mesh是用于构建3D模型的基本组成部分之一。

Mesh是Unity中许多3D对象(如MeshFilter、MeshRenderer等)的基础,通过MeshFilter组件将Mesh应用到GameObject上,并使用MeshRenderer来渲染对象。通常,开发者使用Mesh来创建静态或动态的3D模型,并在游戏场景中呈现出来。

vertices表示网格的顶点数组。
triangles表示定义三角形的索引数组。
normals表示法线数组,用于指定网格每个顶点的法线方向。
uv表示纹理坐标数组。
colors表示网格的顶点颜色。
SetIndicesSetIndices 是 Mesh 类中用于设置网格顶点索引的方法。它允许您指定用于连接顶点以形成三角形或其他多边形的索引数组。
MarkDynamicMarkDynamic 方法用于标记网格为动态网格。它是一个性能优化方法,用于告诉引擎此网格将频繁地更新。当您有一个需要在每帧或频繁时间间隔内更新的网格时,可以使用 MarkDynamic 方法。

1、绘制正方体线框

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

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class DrawCube : MonoBehaviour
{
    private Mesh mesh;
    private MeshFilter meshFilter;
    private MeshRenderer meshRenderer;

    // 创建一个立方体的 Mesh
    private Mesh CreateCubeMesh()
    {
        Mesh mesh = new Mesh();
        mesh.vertices = new Vector3[]
        {
            new Vector3(-1, -1, -1), // 0
            new Vector3(1, -1, -1),  // 1
            new Vector3(1, 1, -1),   // 2
            new Vector3(-1, 1, -1),  // 3
            new Vector3(-1, -1, 1),  // 4
            new Vector3(1, -1, 1),   // 5
            new Vector3(1, 1, 1),    // 6
            new Vector3(-1, 1, 1)    // 7
        };

        mesh.SetIndices(new int[]
        {
            0, 1, 1, 2, 2, 3, 3, 0, // 前面四条边
            4, 5, 5, 6, 6, 7, 7, 4, // 后面四条边
            0, 4, 1, 5, 2, 6, 3, 7  // 连接前后两个面的四条边
        }, MeshTopology.Lines, 0);

        return mesh;
    }


    private void Start()
    {
        meshFilter = GetComponent<MeshFilter>();
        meshRenderer = GetComponent<MeshRenderer>();

        mesh = CreateCubeMesh();
        meshFilter.mesh = mesh;

        var material = new Material(Shader.Find("Unlit/Color"));
        material.color = Color.green;
        meshRenderer.material = material;
    }
}

这里是通过创建一个正方体的Mesh,然后通过MeshFilter组件将Mesh应用到GameObject上,并使用MeshRenderer来渲染该正方体线框。

四、GL

OpenGL(Open Graphics Library)是一个用于渲染 2D 和 3D 图形的跨平台图形库。它提供了一系列函数和指令,允许开发者通过编程来操作图形硬件,实现图形渲染和交互式图形应用程序的开发。

在Unity中,GL(Graphics Library)是一个底层的图形渲染接口,用于执行低级图形绘制操作。GL允许开发者以非常灵活的方式直接控制图形渲染,使开发者可以绘制各种形状、线条、文本和纹理,实现各种自定义的绘图需求。

调用方式:

OnPostRender(): 用于在完成渲染场景之后立即调用,适合进行屏幕后处理或绘制Overlay UI。
OnRenderObject(): 在渲染对象时调用。允许手动渲染对象并覆盖其默认渲染。用于自定义渲染对象或其他特殊渲染需求。

显示范围:

LoadOrtho(): 用于设置绘制范围为屏幕坐标系,绘制在整个屏幕上。在OnPostRender()中调用,以便以屏幕为基础绘制2D图形。

材质设置:

GL允许使用材质,但与在Unity中常规渲染管道中的应用方式有所不同。
在GL中,使用材质时,需要在GL代码中直接调用SetPass()来设置所需的材质属性。这将设置着色器状态,让GL能够使用该材质来渲染几何图元。
若要控制颜色,需要使用GL.Color()方法设置颜色。
若要控制透明度,可以通过设置颜色的Alpha值来实现半透明效果。

1、绘制3D网格和屏幕网格

using UnityEngine;

public class DrawGrid : MonoBehaviour
{
	public float gridSize = 1.0f; // 网格单元的大小
    public int gridSizeX = 10; // 网格的列数
    public int gridSizeY = 10; // 网格的行数
    private Material lineMaterial;


    void CreateLineMaterial()
    {
        if (!lineMaterial)
        {
            // Unity has a built-in shader that is useful for drawing
            // simple colored things.
            Shader shader = Shader.Find("Hidden/Internal-Colored");
            lineMaterial = new Material(shader);
            lineMaterial.hideFlags = HideFlags.HideAndDontSave;
            // Turn on alpha blending
            lineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
            lineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
            // Turn backface culling off
            lineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
            // Turn off depth writes
            lineMaterial.SetInt("_ZWrite", 0);
        }
    }

    // Will be called after all regular rendering is done
    public void OnRenderObject()
    {
        CreateLineMaterial();
        lineMaterial.SetPass(0);                //刷新当前材质  

        //Draw3DGrid();
        DrawScreenGrid();
    }
	
	 /// <summary>
    /// 在三维场景中绘制网格
    /// </summary>
    void Draw3DGrid()
    {
        GL.PushMatrix();
        GL.MultMatrix(transform.localToWorldMatrix);
        GL.Begin(GL.LINES);

        float startX = -(gridSize * gridSizeX) / 2;
        float startZ = -(gridSize * gridSizeY) / 2;

        // 绘制垂直方向的线条
        for (int i = 0; i <= gridSizeX; i++)
        {
            GL.Color(Color.red);
            float xPos = startX + i * gridSize;
            GL.Vertex3(xPos, 0, startZ);
            GL.Vertex3(xPos, 0, -startZ);
        }

        // 绘制水平方向的线条
        for (int i = 0; i <= gridSizeY; i++)
        {
            GL.Color(Color.green);

            float zPos = startZ + i * gridSize;
            GL.Vertex3(startX, 0, zPos);
            GL.Vertex3(-startX, 0, zPos);
        }

        GL.End();
        GL.PopMatrix();
    }

    /// <summary>
    /// 在屏幕上绘制网格
    /// </summary>
    void DrawScreenGrid()
    {
        GL.PushMatrix(); 			 			//保存当前Matirx  
        GL.LoadPixelMatrix();                   //设置pixelMatrix  

        GL.Begin(GL.LINES);

        // 绘制水平方向的线条
        for (int i = 0; i <= gridSizeX; i++)
        {
            GL.Color(Color.green);

            float xPos = i * gridSize;
            GL.Vertex3(xPos, 0, 0);
            GL.Vertex3(xPos, gridSize * gridSizeY, 0);
        }

        // 绘制垂直方向的线条
        for (int i = 0; i <= gridSizeY; i++)
        {
            GL.Color(Color.green);

            float zPos = i * gridSize;
            GL.Vertex3(0, zPos, 0);
            GL.Vertex3(gridSize * gridSizeX, zPos, 0);
        }

        GL.End();
        GL.PopMatrix();//读取之前的Matrix  
    }
}

2、实现屏幕框选

public class BoxSelection: MonoBehaviour
{
	public Material boxMaterial;
    public Material lineMaterial;

    private Vector3 startPoint;
    private bool isSelecting = false;

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            startPoint = Input.mousePosition;
            isSelecting = true;
        }
        else if (Input.GetMouseButtonUp(0))
        {
            isSelecting = false;
            SelectObjects();
        }
    }

    private void OnPostRender()
    {
       	if (!boxMaterial || !lineMaterial)
        {
            Debug.LogError("Please assign materials on the inspector!");
            return;
        }

        if (isSelecting)
        {
            GL.PushMatrix();
            boxMaterial.SetPass(0);
            GL.LoadPixelMatrix();

            GL.Begin(GL.QUADS);
            boxMaterial.color = new Color(1f, 1f, 1f, 0.2f);

            Vector3 endPos = Input.mousePosition;
            GL.Vertex3(startPoint.x, startPoint.y, 0);
            GL.Vertex3(endPos.x, startPoint.y, 0);
            GL.Vertex3(endPos.x, endPos.y, 0);
            GL.Vertex3(startPoint.x, endPos.y, 0);

            GL.End();
            GL.PopMatrix();

            GL.PushMatrix();
            lineMaterial.SetPass(0);
            GL.LoadPixelMatrix();

            GL.Begin(GL.LINES);
            lineMaterial.color = Color.green;

            GL.Vertex3(startPoint.x, startPoint.y, 0);
            GL.Vertex3(endPos.x, startPoint.y, 0);

            GL.Vertex3(endPos.x, startPoint.y, 0);
            GL.Vertex3(endPos.x, endPos.y, 0);

            GL.Vertex3(endPos.x, endPos.y, 0);
            GL.Vertex3(startPoint.x, endPos.y, 0);

            GL.Vertex3(startPoint.x, endPos.y, 0);
            GL.Vertex3(startPoint.x, startPoint.y, 0);

            GL.End();
            GL.PopMatrix();
        }
    }

    private void SelectObjects()
    {
       Vector3 mouseStartPos = startPoint;
        Vector3 mouseEndPos = Input.mousePosition;

        Vector3 min = Vector3.Min(mouseStartPos, mouseEndPos);
        Vector3 max = Vector3.Max(mouseStartPos, mouseEndPos);

        Rect selectRect = new Rect(min.x, Screen.height - max.y, max.x - min.x, max.y - min.y);

        foreach (GameObject obj in FindObjectsOfType<GameObject>())
        {
            Vector3 screenPos = Camera.main.WorldToScreenPoint(obj.transform.position);
            if (selectRect.Contains(screenPos))
            {
                Debug.Log("Selected object: " + obj.name);
                // 在这里可以添加选中对象的操作逻辑
            }
        }
    }
}

五、LineRenderer

LineRenderer 是 Unity 中用于在场景中绘制线条的组件之一。它可以用于创建简单的线段、路径、连线等效果。

1、实现屏幕写字板

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

public class LineRendererDraw : MonoBehaviour
{
    private LineRenderer clone;
    public LineRenderer linePre;
    private int positionCount;
    private Material lineMaterial;

    private void Start()
    {
        lineMaterial = new Material(Shader.Find("Legacy Shaders/Particles/Additive"));
        linePre.material = lineMaterial;
    }

    /// <summary>
    /// 创建线条
    /// </summary>
    /// <returns></returns>
    private LineRenderer CreateLine()
    {
        //实例化对象
        LineRenderer line = Instantiate(linePre, linePre.transform.position, Quaternion.identity);

        //设置起始和结束的颜色
        line.startColor = Color.red;
        line.endColor = Color.blue;

        //设置起始和结束的宽度
        line.startWidth = 0.4f;
        line.endWidth = 0.35f;

        return line;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //实例化对象
            clone = CreateLine();

            //计数
            positionCount = 0;
        }
        if (Input.GetMouseButton(0))
        {
            //每一帧检测,按下鼠标的时间越长,计数越多
            positionCount++;

            //设置顶点数
            clone.positionCount = positionCount;

            //设置顶点位置(顶点的索引,将鼠标点击的屏幕坐标转换为世界坐标)
            clone.SetPosition(positionCount - 1, Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 15)));
        }
    }
}

六、UI画线

这里通过Unity的UGUI来进行画线,主要原理就是使用OnPopulateMesh方法来重构Mesh进行画线。

OnPopulateMesh函数:当一个UI元素生成顶点数据时会调用。

OnPopulateMesh(VertexHelper vh)函数,我们可以在这个函数中修改顶点的数据或者获取顶点的数据。

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

/// <summary>
/// 绘制的线段结构体
/// </summary>
public struct LineSegment
{
    public Vector3 startPoint;
    public Vector3 endPoint;
    public float lineWidth;

    public Vector3 Vector
    {
        get
        {
            return endPoint - startPoint;
        }
    }

    public Vector3 Normal
    {
        get
        {
            return Vector3.Cross(Vector.normalized, Vector3.forward).normalized;
        }
    }

    public Vector3 StartLeftPoint
    {
        get
        {
            return startPoint + Normal * lineWidth; 
        }
    }

    public Vector3 StartRightPoint 
    {
        get
        {
            return startPoint - Normal * lineWidth;
        }
    }

    public Vector3 EndLeftPoint
    {
        get
        {
            return endPoint + Normal * lineWidth; 
        }
    }

    public Vector3 EndRightPoint
    {
        get
        {
            return endPoint - Normal * lineWidth;
        }
    }
}

public class ImageLine : MaskableGraphic
{
    private List<List<UIVertex>> vertexQuadList = new List<List<UIVertex>>();

    private LineSegment lineSegment = new LineSegment();
   
    public float lineWidth = 4;

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();

        for (int i = 0; i < vertexQuadList.Count; i++)
        {
            vh.AddUIVertexQuad(vertexQuadList[i].ToArray());
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            lineSegment.lineWidth = lineWidth;

            lineSegment.startPoint = ScreenPointToLocalPointInRectangle(Input.mousePosition);

        }
        else if (Input.GetMouseButton(0))
        {
            lineSegment.endPoint = ScreenPointToLocalPointInRectangle(Input.mousePosition);

            //当鼠标不动时不再绘制
            if (lineSegment.startPoint == lineSegment.endPoint) return;

            //线段过短不进行绘制
            if (lineSegment.Vector.magnitude < 5) return;

            AddVertexQuad(lineSegment);

            lineSegment.startPoint = lineSegment.endPoint;

            SetVerticesDirty();
        }

        if (Input.GetMouseButtonDown(1))
        {
            vertexQuadList.Clear();
            SetVerticesDirty();
        }
    }

    /// <summary>
    /// 将线段上顶点添加到UI四边形顶点
    /// </summary>
    /// <param name="lineSegment"></param>
    private void AddVertexQuad(LineSegment lineSegment)
    {
        List<UIVertex> uIVertices = new List<UIVertex>();

        UIVertex uIVertex = new UIVertex();
        uIVertex.position = lineSegment.StartLeftPoint;
        uIVertex.color = color;
        uIVertices.Add(uIVertex);

        UIVertex uIVertex1 = new UIVertex();
        uIVertex1.position = lineSegment.StartRightPoint;
        uIVertex1.color = color;
        uIVertices.Add(uIVertex1);

        UIVertex uIVertex2 = new UIVertex();
        uIVertex2.position = lineSegment.EndRightPoint;
        uIVertex2.color = color;
        uIVertices.Add(uIVertex2);

        UIVertex uIVertex3 = new UIVertex();
        uIVertex3.position = lineSegment.EndLeftPoint;
        uIVertex3.color = color;
        uIVertices.Add(uIVertex3);

        vertexQuadList.Add(uIVertices);
    }

    /// <summary>
    /// 屏幕坐标转换为本地坐标
    /// </summary>
    /// <param name="screenPoint"></param>
    /// <returns></returns>
    private Vector2 ScreenPointToLocalPointInRectangle(Vector3 screenPoint)
    {
        RectTransform rectTransform = GetComponent<RectTransform>();
        Vector2 localPoint = Vector2.zero;

        switch (canvas.renderMode)
        {
            case RenderMode.ScreenSpaceOverlay:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, null, out localPoint);
                break;
            case RenderMode.ScreenSpaceCamera:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, canvas.worldCamera, out localPoint);
                break;
            case RenderMode.WorldSpace:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, canvas.worldCamera, out localPoint);
                break;
            default:
                break;
        }

        return localPoint;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1587018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

rust使用print控制台打印输出五颜六色的彩色红色字体

想要在控制台打印输出彩色的字体&#xff0c;可以使用一些已经封装好的依赖库&#xff0c;比如ansi_term这个依赖库&#xff0c;官方依赖库地址&#xff1a;https://crates.io/crates/ansi_term 安装依赖&#xff1a; cargo add ansi_term 或者在Cargo.toml文件中加入&#…

HWOD:在含有空格的字符串中统计大写字母的个数

一、知识点 回车键的ASCII码是10 二、题目 1、描述 找出给定字符串中大写字符(即A-Z)的个数。 数据范围&#xff1a;字符串长度&#xff1a;1≤∣s∣≤250 字符串中可能包含空格或其他字符 2、输入 对于每组样例&#xff0c;输入一行&#xff0c;代表待统计的字符串 …

DCDC 5V2A电源升压芯片FP6276BXR-G1 FP6298XR-G1

一、FP6276BXR-G1 3.7v升5V2A同步升压输入电压:2.4V-4.5V FP6276B是一个具有PWM/PSM控制的电流模式增压直流-直流转换器。它的PWM电路内置40mΩ高侧开关和40mΩ低侧开关使该调节器高高效。内部补偿网络还将外部组件计数最小化到只有6个。一个内部的0.6V电压被连接到误差放大器…

玩机进阶教程------手机定制机 定制系统 解除系统安装软件限制的一些步骤解析

定制机 在于各工作室与商家合作定制rom中有一些定制机。限制用户私自安装第三方软件。或者限制解锁 。无法如正常机登陆账号等等。定制机一般用于固定行业或者一些部门。专机专用。例如很多巴枪扫描机型等等。或者一些小牌机型。对于没有官方包的机型首先要导出各个分区来制作…

Java快速入门系列-8(Web开发基础)

第8章 Web开发基础 8.1 Servlet与JSP8.1.1 Servlet简介8.1.2 JSP简介与使用8.1.3 Servlet与JSP协作8.2 Web服务器与Tomcat8.2.1 安装与配置Tomcat8.2.2 配置与管理Web应用8.3 MVC设计模式与Java Web应用8.3.1 MVC原理8.3.2 MVC在Java Web中的应用8.4 RESTful API设计与实现8.4.…

学习R语言第二天

R语言可以做什么 1.数据分析 R语言如何使用 1. 请看我的操作方式 2. 如何获取当前路径 -- 获取当前路径 > getwd() [1] "E:/R/RWorkSpace/day01" -- 修改当前路径 > setwd(dir "E:/R") > getwd() [1] "E:/R" 3.查看当下数据值的信…

计算机毕业设计 工厂车间设备管理系统php+vue.js

该系统是以PHP为主要开发语言&#xff0c;集合MySQL数据库技术构建基于Web的以信息为目标的&#xff0c;动态的交互平台 PHP与Apache&#xff0c;MySQL的组合虽然有着诸多优势&#xff0c;但三种出自不同作者的开源软件要能很好的配合工作&#xff0c;需要很多手工配置&#x…

源码解析HashMap的put方法

前言 HashMap 基于哈希表的 Map 接口实现&#xff0c;其中的值是以 key-value 存储形式存在&#xff0c;即主要用来存放键值对。它的 key、value 都可以为 null&#xff0c;此外&#xff0c;HashMap 中的映射不是有序的。那么本篇文章将从源码的角度来很详细地讲解HashMap中pu…

5G智慧水利数字孪生可视化平台,推进水利行业数字化转型

5G智慧水利数字孪生可视化平台&#xff0c;推进水利行业数字化转型。随着5G技术的快速发展&#xff0c;越来越多的行业开始探索数字化转型的道路。水利行业作为国民经济的重要支柱&#xff0c;也面临着数字化转型的迫切需求。5G智慧水利数字孪生可视化平台作为水利行业数字化转…

微服务-7 Docker

一、镜像、容器、仓库 容器是镜像的实例&#xff0c;仓库中存储着镜像。 二、镜像的操作 三、容器的操作 创建容器停止容器&#xff0c;查看后发现没有了(docker ps 默认只展示没有停止的) docker ps -a (可以展示运行中和停止的镜像)删除容器&#xff1a;(docker rm 不能删除…

LangChain-18 Caching 将回答内容进行缓存 可在内存中或数据库中持久化缓存

背景描述 可以将问答的内容缓存起来&#xff0c;如果是相同的问题&#xff0c;那么将会直接把答案返回去&#xff0c;可以节约费用和计算。 安装依赖 pip install -qU langchain-core langchain-openai编写代码 我们可以通过 InMemoryCache 进行内存缓存 或者 SQLiteCache …

【C++题解】1605. 求一个两位数的个位和十位的和

问题&#xff1a;1605. 求一个两位数的个位和十位的和 类型&#xff1a;基本运算、拆位求解。 题目描述&#xff1a; 从键盘读入一个两位的整数 n &#xff0c;请求出这个两位整数个位和十位的和是多少&#xff1f; 输入&#xff1a; 一个两位的整数 n 。 输出&#xff1a…

R语言ggplot2绘图学习笔记(基础知识大全)

R语言ggplot2绘图入门笔记 今天分享的内容是在R语言中利用ggplot2进行可视化的入门笔记&#xff0c;适用于初学者了解ggplot2绘图系统。干货满满&#xff0c;建议收藏&#xff01; 首先安装以下R包&#xff1a; install.packages(c("tidyverse", "colorspace&qu…

机器学习-09-图像处理01-理论

总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍机器学习中图像处理技术。 参考 02图像知识 色彩基础知识整理-色相、饱和度、明度、色调 图像特征提取&#xff08;VGG和Resnet特征提取卷积过程详解&#xff09; Python图像处理入门 【人工智能】PythonOpenCV…

PostgreSQL强势崛起,选择它还是MySQL

大家好&#xff0c;关系型数据库&#xff08;RDBMS&#xff09;作为数据管理的基石&#xff0c;自数据仓库兴起之初便扮演着核心角色&#xff0c;并在数据科学的发展浪潮中持续发挥着价值。即便在人工智能和大型语言模型&#xff08;LLM&#xff09;日益成熟的今天&#xff0c;…

【方法】PDF密码如何取消?

对于重要的PDF文件&#xff0c;很多人会设置密码保护&#xff0c;那后续不需要保护了&#xff0c;如何取消密码呢&#xff1f; 今天我们来看看&#xff0c;PDF的两种密码&#xff0c;即“限制密码”和“打开密码”&#xff0c;是如何取消的&#xff0c;以及忘记密码的情况要怎…

2024考研调剂须知

----------------------------------------------------------------------------------------------------- 考研复试科研背景提升班 教你快速深入了解掌握考研复试面试中的常见问题以及注意事项&#xff0c;系统的教你如何在短期内快速提升自己的专业知识水平和编程以及英语…

ArcGIS Desktop使用入门(三)图层右键工具——缩放至图层、缩放至可见

系列文章目录 ArcGIS Desktop使用入门&#xff08;一&#xff09;软件初认识 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——标准工具 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——编辑器 ArcGIS Desktop使用入门&#xff08;二&#x…

php-redis windows ,pecl 已经不维护了,解决方案:php 8.2 | 8.3+ redis extension windows

从论坛上pecl 已经不维护了&#xff0c;直接让大家到ci 去下载 https://stackoverflow.com/questions/76496488/redis-dll-not-found-for-php8-2/76496489#76496489 让我们找最新的一次commit &#xff0c;然后又action 构建&#xff0c;再下载&#xff0c;这样的话也好&#…

【STM32嵌入式系统设计与开发】——17ADC(ADC按键应用)

这里写目录标题 STM32资料包&#xff1a; 百度网盘下载链接&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1mWx9Asaipk-2z9HY17wYXQ?pwd8888 提取码&#xff1a;8888 一、任务描述二、任务实施1、工程文件夹创建2、函数编辑&#xff08;1&#xff09;主函数编辑&#…