UE蓝图 返回结果(FunctionResult)节点和源码

系列文章目录

UE蓝图 Get节点和源码
UE蓝图 Set节点和源码
UE蓝图 Cast节点和源码
UE蓝图 分支(Branch)节点和源码
UE蓝图 入口(FunctionEntry)节点和源码
UE蓝图 返回结果(FunctionResult)节点和源码


文章目录

  • 系列文章目录
  • 一、FunctionResult节点功能
  • 二、FunctionResult节点用法
  • 三、使用场景
  • 四、实现过程
  • 五、相关源码


一、FunctionResult节点功能

在这里插入图片描述

FunctionResult节点是UE蓝图中用于返回函数执行结果的重要节点之一。它可以帮助您将函数的返回值传递给调用者,并在需要时进行调试和测试。FunctionResult节点通常位于函数的末尾。


二、FunctionResult节点用法

以下是使用FunctionResult节点的一般步骤:

  1. 创建FunctionResult节点:在蓝图中,定义了函数的返回参数后,FunctionResult节点会自动创建显示。
  2. 连接输入引脚:如果函数需要输出参数,你可以将相应的引脚连接到FunctionResult节点的输入引脚上。
  3. 使用返回值:你可以将FunctionResult节点的输出引脚连接到其他节点,以便基于函数的返回值执行进一步的操作。

三、使用场景

UE(Unreal Engine)的蓝图系统中的FunctionResult节点具有多种应用场景,主要涉及到需要获取函数返回值并进行进一步处理的情况。以下是一些常见的应用场景示例:

  1. 条件判断

    • 当你的游戏逻辑需要根据某个函数的返回值来做出决策时,可以使用FunctionResult节点来存储这个返回值,并将其连接到条件判断节点(如Branch节点)上。例如,一个函数可能返回一个布尔值来表示某个条件是否满足,你可以使用FunctionResult节点来捕获这个布尔值,并根据其值来执行不同的逻辑分支。
  2. 变量赋值与状态更新

    • 在游戏运行过程中,你可能需要更新某些变量的值或游戏状态。这些变量或状态可能由某个函数的返回值决定。通过FunctionResult节点,你可以获取函数的返回值,并将其赋给蓝图中的变量或用于更新游戏状态。
  3. 事件响应

    • 在UE中,事件是驱动游戏逻辑的重要机制。当某个事件发生时(如用户点击按钮、碰撞检测等),你可能会调用一个函数来处理这个事件,并根据函数的返回值来执行后续操作。FunctionResult节点可以帮助你捕获这些返回值,并据此作出响应。
  4. 数据传递与处理

    • 在复杂的游戏逻辑中,数据可能需要在不同的节点和函数之间传递。FunctionResult节点可以作为数据传递的桥梁,将一个函数的返回值传递给另一个函数或节点进行进一步处理。这种传递可以是数值、对象引用、字符串等各种数据类型。
  5. 异步操作

    • 在UE中,有些函数可能是异步执行的,即它们不会立即返回结果,而是在一段时间后通过回调或事件来通知结果。在这种情况下,你可以使用FunctionResult节点来等待异步操作完成并获取其结果。这通常涉及到使用延迟节点(Delay)和事件调度(Event Dispatch)来管理异步逻辑。

需要注意的是,虽然FunctionResult节点在蓝图系统中非常有用,但它只适用于能够返回值的函数。对于没有返回值的函数(返回类型为void),FunctionResult节点将不会有任何作用。此外,如果函数有多个返回值,你可能需要使用多个FunctionResult节点或者使用结构体(Struct)来封装多个返回值。

总之,FunctionResult节点在UE蓝图系统中广泛应用于条件判断、变量赋值、事件响应、数据传递和异步操作等场景,帮助开发者更加灵活地管理和处理函数的返回值。

四、实现过程

  • 创建输入引脚
  • 调用FKCHandler_FunctionEntry.RegisterNet注册返回值引脚
virtual void RegisterNet(FKismetFunctionContext& Context, UEdGraphPin* Net) override
{
	// Do not register as a default any Pin that comes from being Split
	if (Net->ParentPin == nullptr)
	{
		FString NetPinName = Net->PinName.ToString();
		for (FBPTerminal& ResultTerm : Context.Results)
		{
			if ((ResultTerm.Name == NetPinName) && (ResultTerm.Type == Net->PinType))
			{
				Context.NetMap.Add(Net, &ResultTerm);
				return;
			}
		}
		FBPTerminal* Term = new FBPTerminal();
		Context.Results.Add(Term);
		Term->CopyFromPin(Net, MoveTemp(NetPinName));
		Context.NetMap.Add(Net, Term);
	}
}
  • 调用Compile编译创建Statement
	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		static const FBoolConfigValueHelper ExecutionAfterReturn(TEXT("Kismet"), TEXT("bExecutionAfterReturn"), GEngineIni);

		if (ExecutionAfterReturn)
		{
			// for backward compatibility only
			FKCHandler_VariableSet::Compile(Context, Node);
		}
		else
		{
			GenerateAssigments(Context, Node);

			if (Context.IsDebuggingOrInstrumentationRequired() && Node)
			{
				FBlueprintCompiledStatement& TraceStatement = Context.AppendStatementForNode(Node);
				TraceStatement.Type = Context.GetWireTraceType();
				TraceStatement.Comment = Node->NodeComment.IsEmpty() ? Node->GetName() : Node->NodeComment;
			}

			// always go to return
			FBlueprintCompiledStatement& GotoStatement = Context.AppendStatementForNode(Node);
			GotoStatement.Type = KCST_GotoReturn;
		}
	}

五、相关源码

源码文件:
K2Node_FunctionResult.h
K2Node_FunctionResult.cpp
相关类:
FKCHandler_FunctionResult
K2Node_FunctionResult
在这里插入图片描述


class FKCHandler_FunctionResult : public FKCHandler_VariableSet
{
public:
	FKCHandler_FunctionResult(FKismetCompilerContext& InCompilerContext)
		: FKCHandler_VariableSet(InCompilerContext)
	{
	}

	virtual void RegisterNet(FKismetFunctionContext& Context, UEdGraphPin* Net) override
	{
		// Do not register as a default any Pin that comes from being Split
		if (Net->ParentPin == nullptr)
		{
			FString NetPinName = Net->PinName.ToString();
			for (FBPTerminal& ResultTerm : Context.Results)
			{
				if ((ResultTerm.Name == NetPinName) && (ResultTerm.Type == Net->PinType))
				{
					Context.NetMap.Add(Net, &ResultTerm);
					return;
				}
			}
			FBPTerminal* Term = new FBPTerminal();
			Context.Results.Add(Term);
			Term->CopyFromPin(Net, MoveTemp(NetPinName));
			Context.NetMap.Add(Net, Term);
		}
	}

	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		static const FBoolConfigValueHelper ExecutionAfterReturn(TEXT("Kismet"), TEXT("bExecutionAfterReturn"), GEngineIni);

		if (ExecutionAfterReturn)
		{
			// for backward compatibility only
			FKCHandler_VariableSet::Compile(Context, Node);
		}
		else
		{
			GenerateAssigments(Context, Node);

			if (Context.IsDebuggingOrInstrumentationRequired() && Node)
			{
				FBlueprintCompiledStatement& TraceStatement = Context.AppendStatementForNode(Node);
				TraceStatement.Type = Context.GetWireTraceType();
				TraceStatement.Comment = Node->NodeComment.IsEmpty() ? Node->GetName() : Node->NodeComment;
			}

			// always go to return
			FBlueprintCompiledStatement& GotoStatement = Context.AppendStatementForNode(Node);
			GotoStatement.Type = KCST_GotoReturn;
		}
	}

	virtual bool RequiresRegisterNetsBeforeScheduling() const override
	{
		return true;
	}
};

#if WITH_EDITORONLY_DATA
namespace
{
	void GatherFunctionResultNodeForLocalization(const UObject* const Object, FPropertyLocalizationDataGatherer& PropertyLocalizationDataGatherer, const EPropertyLocalizationGathererTextFlags GatherTextFlags)
	{
		const UK2Node_FunctionResult* const FunctionResultNode = CastChecked<UK2Node_FunctionResult>(Object);

		// Function Result (aka, Return) nodes always report their values as being the default
		// but we still need to gather them as they are the only place the values are defined
		const FString PathToObject = FunctionResultNode->GetPathName();
		for (const UEdGraphPin* Pin : FunctionResultNode->Pins)
		{
			if (!Pin->DefaultTextValue.IsEmpty())
			{
				PropertyLocalizationDataGatherer.GatherTextInstance(Pin->DefaultTextValue, FString::Printf(TEXT("%s.%s"), *PathToObject, *Pin->GetName()), /*bIsEditorOnly*/true);
			}
		}

		PropertyLocalizationDataGatherer.GatherLocalizationDataFromObject(FunctionResultNode, GatherTextFlags);
	}
}
#endif

UK2Node_FunctionResult::UK2Node_FunctionResult(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
#if WITH_EDITORONLY_DATA
	{ static const FAutoRegisterLocalizationDataGatheringCallback AutomaticRegistrationOfLocalizationGatherer(UK2Node_FunctionResult::StaticClass(), &GatherFunctionResultNodeForLocalization); }
#endif
}

FText UK2Node_FunctionResult::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	if (ENodeTitleType::MenuTitle == TitleType)
	{
		return NSLOCTEXT("K2Node", "ReturnNodeMenuTitle", "Add Return Node...");
	}
	return NSLOCTEXT("K2Node", "ReturnNode", "Return Node");
}

void UK2Node_FunctionResult::AllocateDefaultPins()
{
	CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);

	if (UFunction* const Function = FunctionReference.ResolveMember<UFunction>(GetBlueprintClassFromNode()))
	{
		CreatePinsForFunctionEntryExit(Function, /*bIsFunctionEntry=*/ false);
	}

	Super::AllocateDefaultPins();

	FFillDefaultPinValueHelper::FillAll(this);
}

bool UK2Node_FunctionResult::CanCreateUserDefinedPin(const FEdGraphPinType& InPinType, EEdGraphPinDirection InDesiredDirection, FText& OutErrorMessage)
{
	bool bResult = Super::CanCreateUserDefinedPin(InPinType, InDesiredDirection, OutErrorMessage);
	if (bResult)
	{
		if(InDesiredDirection == EGPD_Output)
		{
			OutErrorMessage = NSLOCTEXT("K2Node", "AddOutputPinError", "Cannot add output pins to function result node!");
			bResult = false;
		}
	}
	return bResult;
}

UEdGraphPin* UK2Node_FunctionResult::CreatePinFromUserDefinition(const TSharedPtr<FUserPinInfo> NewPinInfo)
{
	UEdGraphPin* Pin = CreatePin(EGPD_Input, NewPinInfo->PinType, NewPinInfo->PinName);
	CastChecked<UEdGraphSchema_K2>(GetSchema())->SetPinAutogeneratedDefaultValue(Pin, NewPinInfo->PinDefaultValue);
	return Pin;
}

void UK2Node_FunctionResult::FixupPinStringDataReferences(FArchive* SavingArchive)
{
	Super::FixupPinStringDataReferences(SavingArchive);
	if (SavingArchive)
	{
		UpdateUserDefinedPinDefaultValues();
	}
}

FNodeHandlingFunctor* UK2Node_FunctionResult::CreateNodeHandler(FKismetCompilerContext& CompilerContext) const
{
	return new FKCHandler_FunctionResult(CompilerContext);
}

FText UK2Node_FunctionResult::GetTooltipText() const
{
	return NSLOCTEXT("K2Node", "ReturnNodeTooltip", "The node terminates the function's execution. It returns output parameters.");
}

void UK2Node_FunctionResult::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
	// actions get registered under specific object-keys; the idea is that 
	// actions might have to be updated (or deleted) if their object-key is  
	// mutated (or removed)... here we use the node's class (so if the node 
	// type disappears, then the action should go with it)
	UClass* ActionKey = GetClass();
	// to keep from needlessly instantiating a UBlueprintNodeSpawner, first   
	// check to make sure that the registrar is looking for actions of this type
	// (could be regenerating actions for a specific asset, and therefore the 
	// registrar would only accept actions corresponding to that asset)
	if (ActionRegistrar.IsOpenForRegistration(ActionKey))
	{
		UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass());
		check(NodeSpawner != nullptr);

		ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner);
	}
}

bool UK2Node_FunctionResult::IsCompatibleWithGraph(UEdGraph const* Graph) const
{
	auto K2Schema = Cast<const UEdGraphSchema_K2>(Graph ? Graph->GetSchema() : nullptr);
	const bool bIsConstructionScript = (K2Schema != nullptr) ? K2Schema->IsConstructionScript(Graph) : false;
	const bool bIsCompatible = (K2Schema != nullptr) ? (EGraphType::GT_Function == K2Schema->GetGraphType(Graph)) : false;
	return bIsCompatible && !bIsConstructionScript && Super::IsCompatibleWithGraph(Graph);
}

TArray<UK2Node_FunctionResult*> UK2Node_FunctionResult::GetAllResultNodes() const
{
	TArray<UK2Node_FunctionResult*> AllResultNodes;
	if (auto Graph = GetGraph())
	{
		Graph->GetNodesOfClass(AllResultNodes);
	}
	return AllResultNodes;
}

void UK2Node_FunctionResult::PostPlacedNewNode()
{
	Super::PostPlacedNewNode();

	// adhere to the function's inherited signature (if there is one)
	SyncWithEntryNode();
	// reflect any user added outputs (tracked by pre-existing result nodes)
	SyncWithPrimaryResultNode();
}

void UK2Node_FunctionResult::PostPasteNode()
{
	Super::PostPasteNode();

	// adhere to the function's inherited signature (if there is one)
	SyncWithEntryNode();
	// reflect any user added outputs (tracked by pre-existing result nodes)
	SyncWithPrimaryResultNode();
	// reflect editability of node in pins
	MakePinsEditable();
}

bool UK2Node_FunctionResult::CanUserDeleteNode() const
{
	bool bCanDelete = true;
	if (!bIsEditable)
	{
		if (UEdGraph* Graph = GetGraph())
		{
			bCanDelete = false;
			for (UEdGraphNode* Node : Graph->Nodes)
			{
				UK2Node_FunctionResult* ResultNode = Cast<UK2Node_FunctionResult>(Node);
				if (ResultNode && ResultNode != this)
				{
					bCanDelete = true;
					break;
				}
			}
		}
	}
	return bCanDelete;
}

void UK2Node_FunctionResult::SyncWithEntryNode()
{
	bool bWasSignatureMismatched = false;
	if (UEdGraph* Graph = GetGraph())
	{
		for (UEdGraphNode* Node : Graph->Nodes)
		{
			if (UK2Node_FunctionEntry* EntryNode = Cast<UK2Node_FunctionEntry>(Node))
			{
				bWasSignatureMismatched = !EntryNode->FunctionReference.IsSameReference(FunctionReference) || (!EntryNode->bIsEditable && UserDefinedPins.Num() > 0);

				// If the entry is editable, so is the result
				bIsEditable = EntryNode->bIsEditable;
				FunctionReference = EntryNode->FunctionReference;
				break;
			}
		}
	}

	if (bWasSignatureMismatched)
	{
		// to handle pasting of a result node from one function into another;
		// if the new function is not editable (like for one that is overidden), 
		// then we shouldn't have userdefined pins
		if (!bIsEditable)
		{
			// iterate backwards so we can remove items from the list as we go
			for (int32 UserPinIndex = UserDefinedPins.Num() - 1; UserPinIndex >= 0; --UserPinIndex)
			{
				RemoveUserDefinedPin(UserDefinedPins[UserPinIndex]);
			}
		}
		
		ReconstructNode();
	}
}

void UK2Node_FunctionResult::SyncWithPrimaryResultNode()
{
	UK2Node_FunctionResult* PrimaryNode = nullptr;
	TArray<UK2Node_FunctionResult*> AllResultNodes = GetAllResultNodes();
	for (auto ResultNode : AllResultNodes)
	{
		if (ResultNode && (this != ResultNode))
		{
			PrimaryNode = ResultNode;
			break;
		}
	}

	if (PrimaryNode)
	{
		FunctionReference = PrimaryNode->FunctionReference;
		bIsEditable = PrimaryNode->bIsEditable;

		// Temporary array that will contain our list of Old Pins that are no longer part of the return signature
		TArray< TSharedPtr<FUserPinInfo> > OldPins = UserDefinedPins;

		// Temporary array that will contain our list of Signature Pins that need to be added
		TArray< TSharedPtr<FUserPinInfo> > SignaturePins = PrimaryNode->UserDefinedPins;

		for (int OldIndex = OldPins.Num() - 1; OldIndex >= 0; --OldIndex)
		{
			TSharedPtr<FUserPinInfo> OldPin = OldPins[OldIndex];

			if (!OldPin.IsValid())
			{
				OldPins.RemoveAt(OldIndex);
			}
			else
			{
				for (int SignatureIndex = SignaturePins.Num() - 1; SignatureIndex >= 0; --SignatureIndex)
				{
					TSharedPtr<FUserPinInfo> SignaturePin = SignaturePins[SignatureIndex];
					if (!SignaturePin.IsValid())
					{
						SignaturePins.RemoveAt(SignatureIndex);
					}
					else if (OldPin->PinName == SignaturePin->PinName &&
						OldPin->PinType == SignaturePin->PinType &&
						OldPin->DesiredPinDirection == SignaturePin->DesiredPinDirection)
					{
						// We have a match between our Signature pins and our Old Pins,
						// so we can leave the old pin as is by removing it from both temporary lists.
						OldPins.RemoveAt(OldIndex);
						SignaturePins.RemoveAt(SignatureIndex);
						break;
					}
				}
			}
		}

		// Remove old pins that are not part of the primary node signature
		for (TSharedPtr<FUserPinInfo> OldPinToRemove : OldPins)
		{
			RemoveUserDefinedPin(OldPinToRemove);
		}

		// Add pins that don't exist yet but are part of the primary node signature
		for (TSharedPtr<FUserPinInfo> SignaturePinToAdd : SignaturePins)
		{
			TSharedPtr<FUserPinInfo> NewPinInfo = MakeShareable(new FUserPinInfo());
			NewPinInfo->PinName = SignaturePinToAdd->PinName;
			NewPinInfo->PinType = SignaturePinToAdd->PinType;
			NewPinInfo->DesiredPinDirection = SignaturePinToAdd->DesiredPinDirection;
			UserDefinedPins.Add(NewPinInfo);
		}

		ReconstructNode();
	}
}

void UK2Node_FunctionResult::MakePinsEditable()
{
	// only do this step if this node is editable
	if (IsEditable())
	{
		// for each pin, excluding the 'exec' pin
		for (int PinIdx = 1; PinIdx < Pins.Num(); ++PinIdx)
		{
			UEdGraphPin* Pin = Pins[PinIdx];
			if (!UserDefinedPinExists(Pin->GetFName()))
			{
				UserDefinedPins.Add(MakeShared<FUserPinInfo>(*Pin));
			}
		}
	}
}

void UK2Node_FunctionResult::ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const
{
	Super::ValidateNodeDuringCompilation(MessageLog);

	auto AllResultNodes = GetAllResultNodes();
	UK2Node_FunctionResult* OtherResult = AllResultNodes.Num() ? AllResultNodes[0] : nullptr;
	if (OtherResult && (OtherResult != this))
	{
		for (auto Pin : Pins)
		{
			auto OtherPin = OtherResult->FindPin(Pin->PinName);
			if (!OtherPin || (OtherPin->PinType != Pin->PinType))
			{
				MessageLog.Error(*NSLOCTEXT("K2Node", "FunctionResult_DifferentReturnError", "Return nodes don't match each other: @@, @@").ToString(), this, OtherResult);
				break;
			}
		}
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

利用数字人技术“活”化吉祥物,打造“科技+”数融盛会

在第十四届全国冬季运动会上&#xff0c;吉祥物“蒙古彩娃”安达和塞努不再同于往常静态的吉祥物形象&#xff0c;而是升级为生动活泼、能够与观众实时互动的数字人形象&#xff0c;活跃于赛事宣传、场馆介绍等多个场景&#xff0c;为本届冰雪盛会注入数字活力&#xff0c;提升…

【SQL注入】靶场SQLI DUMB SERIES-26空格和注释被过滤

26题提示所有的空格和注释都会被过滤掉 输入?id0判断闭合方式&#xff0c;回显报错可以确定闭合方式为单引号 正常思路是需要通过注释符将后面的语句注释掉&#xff0c;但是这一关的注释符被过滤了&#xff0c;可以考虑使用将后面的语句也闭合的思路来避免引号带来的报错。输…

【2024软件测试面试必会技能】Postman(1): postman的介绍和安装

Postman的介绍 Postman 是一款谷歌开发的接口测试工具,使API的调试与测试更加便捷。 它提供功能强大的 Web API & HTTP 请求调试。它能够发送任何类型的HTTP 请求 (GET, HEAD, POST, PUT..)&#xff0c;附带任何数量的参数 headers。 postman是一款支持http协议的接口调试…

获取 Windows 系统托盘图标信息的最新方案(三)

目录 前言 一、实现 CallWndProcHook 二、安装钩子例程 三、创建消息处理窗口 四、完整代码和注意事项 五、总结&更新 文章出处链接:[https://blog.csdn.net/qq_59075481/article/details/136240462] 前言 在《获取 Windows 系统托盘图标信息的最新方案&#xff08…

“目标检测”任务基础认识

“目标检测”任务基础认识 1.目标检测初识 目标检测任务关注的是图片中特定目标物体的位置。 目标检测最终目的&#xff1a;检测在一个窗口中是否有物体。 eg:以猫脸检测举例&#xff0c;当给出一张图片时&#xff0c;我们需要框出猫脸的位置并给出猫脸的大小&#xff0c;如…

MySQL|MySQL基础(求知讲堂-学习笔记【详】)

MySQL基础 目录 MySQL基础一、 MySQL的结构二、 管理数据库1&#xff09;查询所有的数据库2&#xff09;创建数据库3&#xff09;修改数据库的字符编码4&#xff09;删除数据库5&#xff09;切换操作的数据库 三、表的概念四、字段的数据类型4.1 整型4.2 浮点型(float和double)…

MongoDB的介绍和使用

目录 一、MongoDB介绍 二、MongoDB相关概念 三、MongoDB的下载和安装 四、SpringBoot 整合 MongoDB 一、MongoDB介绍 MongoDB是一种NoSQL数据库管理系统&#xff0c;采用面向文档的数据库模型。它以C语言编写&#xff0c;旨在满足大规模数据存储和高性能读写操作的需求。Mo…

如何将 .NET Aspire 应用程序部署到 Azure Container App

作者&#xff1a;Jiachen Jiang 排版&#xff1a;Alan Wang 最近发布的用于构建云原生应用程序的 .NET Aspire 与 Azure Container App&#xff08;ACA&#xff09;非常匹配。.NET Aspire 旨在轻松管理由一系列相互依赖的微服务组成的应用程序。Azure Container App 专为微服务…

Vue样式绑定

1. 绑定 HTML class ①通过class名称的bool值判断样式是否被启用 <template><!--通过样式名称是否显示控制样式--><div :class"{ haveBorder: p.isBorder, haveBackground-color: p.isBackgroundcolor }">此处是样式展示区域</div><br /…

消息队列MQ 保证消息不丢失(消息可靠性)

文章目录 概述RabbitMQ 怎么避免消息丢失&#xff08;可靠传输&#xff09;RocketMQ 怎么确保消息不丢失Kafka 怎么保证消息不丢失activeMQ 怎么避免消息丢失MQ 宕机了消息是否会丢失线上服务宕机时&#xff0c;如何保证数据100%不丢失吗&#xff1f;消息队列消息持久化 概述 …

猫头虎分享已解决Bug || SyntaxError: Unexpected token < in JSON at position 0

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

Docker本地部署Rss订阅工具并实现公网远程访问

文章目录 1. Docker 安装2. Docker 部署Rsshub3. 本地访问Rsshub4. Linux安装Cpolar5. 配置公网地址6. 远程访问Rsshub7. 固定Cpolar公网地址8. 固定地址访问 Rsshub是一个开源、简单易用、易于扩展的RSS生成器&#xff0c;它可以为各种内容生成RSS订阅源。 Rsshub借助于开源社…

一.CMake的工具安装包的下载

下载 cmake工具 进入cmake官网下载cmake&#xff1a;Download CMake 可以选择最新的Windows x64 installer 的包&#xff08;下载需要科学上网&#xff09;

nginx之web性能location优先级

4.2 event事件 events {worker_connections 65536; #设置单个工作进程的最大并发连接数use epoll;#使用epoll事件驱动&#xff0c;Nginx支持众多的事件驱动&#xff0c;比如:select、poll、epoll&#xff0c;只能设置在events模块中设置。accept_mutex on; #on为同一时刻一个…

【刷题】牛客 JZ64 求1+2+3+...+n

刷题 题目描述思路一 &#xff08;暴力递归版&#xff09;思路二 &#xff08;妙用内存版&#xff09;思路三 &#xff08;快速乘法版&#xff09;思路四 &#xff08;构造巧解版&#xff09;Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01…

Flutter 3.19.0 版本新特性

其实在每个版本的更新中呢&#xff0c;都会合并很多很多的这个合并请求、还有开发建议&#xff0c;那么本版本的也不例外&#xff0c;社区官方发布的公告是合并了168个社区成员的1429个拉请求。 当然&#xff0c;如果你的时间允许的话&#xff0c;你可以去查看一下这些请求&am…

Linux篇:进程

一. 前置知识 1.1冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体系 为什么计算机要采用冯诺依曼体系呢&#xff1f; 在计算机出现之前有很多人都提出过计算机体系结构&#xff0c;但最…

linux 网络服务小实验

实验图和要求&#xff1a; 1&#xff09;网关服务器&#xff1a;ens36&#xff1a;12.0.0.254/24&#xff0c;ens33&#xff1a;192.168.44.254/24&#xff1b;Server1&#xff1a;192.168.44.20/24&#xff1b;PC1和Server2&#xff1a;自动获取IP&#xff1b;交换机无需配置。…

仿慕课网html+css+js特效

如果阅读有疑问的话&#xff0c;欢迎评论或私信&#xff01;&#xff01; 本人会很热心的阐述自己的想法&#xff01;谢谢&#xff01;&#xff01;&#xff01; 文章目录 文件目录内容图片部分代码下载路径 文件目录 –css ----index –images –js ----index.js ----jquery.…

MySQL 查询遇到Illegal mix of collations的错误

业务同学线上业务执行 SQL 时报错&#xff0c; ### Error querying database. Cause: java.sql.SQLException: Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8mb4_0900_ai_ci,COERCIBLE) for operation like含义是对like操作非法混合了排序规则(utf8mb4_ge…