Merge branch 'main' of 47.107.44.202:xionglijia/18xchat
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
||||
ProgressBar,
|
||||
Sprite,
|
||||
SpriteFrame,
|
||||
VideoPlayer,
|
||||
} from "cc";
|
||||
import { GButton } from "../../Main/Common/GButton";
|
||||
import ResManager from "../../Main/Manager/ResManager";
|
||||
@@ -60,7 +61,7 @@ export class PreloadUI extends Component {
|
||||
loginBtn: Node;
|
||||
private jinduBar: Node = null;
|
||||
private jinduFilled: Sprite = null;
|
||||
|
||||
private VideoPlayer: VideoPlayer;
|
||||
start() {
|
||||
//Utils.addInnerEL(InnerMsgCode.UI_ShowPrompt, this, this.resiveShowPrompt)
|
||||
Utils.parseNode(this.node, this._nodeTab);
|
||||
@@ -68,6 +69,8 @@ export class PreloadUI extends Component {
|
||||
this.loginBtn = this._nodeTab.btnLogin;
|
||||
this.loginBtn.active = false;
|
||||
|
||||
this.VideoPlayer = this._nodeTab.VideoPlayer.getComponent(VideoPlayer);
|
||||
|
||||
GButton.BandClick(this.loginBtn, this.onLogin, this);
|
||||
|
||||
this.jinduBar = this.node.getChildByName("jinduBar");
|
||||
@@ -81,6 +84,8 @@ export class PreloadUI extends Component {
|
||||
|
||||
this.jinduFilled.fillRange = 0;
|
||||
|
||||
if (!this.VideoPlayer.isPlaying) this.VideoPlayer.play();
|
||||
|
||||
// 初始化配置
|
||||
ConfigManager.I.init();
|
||||
//console.log(ConfigManager.tables.TbGlobalConfig.GameName);
|
||||
@@ -254,10 +259,12 @@ export class PreloadUI extends Component {
|
||||
let res = await CommonService.I.reqResConfig(reqData);
|
||||
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
|
||||
// 保存数据
|
||||
const aiCharacterData = DataManager.I.getDataById<AiCharacterData>(DataId.AiCharacter);
|
||||
const aiCharacterData = DataManager.I.getDataById<AiCharacterData>(
|
||||
DataId.AiCharacter
|
||||
);
|
||||
aiCharacterData.aiCharacter = res.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enterGame() {
|
||||
this.mainScene.init();
|
||||
|
||||
@@ -101,6 +101,10 @@ export class ApiConfig {
|
||||
}
|
||||
}
|
||||
|
||||
public getTimeout() {
|
||||
return this.config.timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证配置是否有效
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,7 @@ import { DataManager, DataId } from "../data/DataManager";
|
||||
import { GirlData } from "../data/GirlData";
|
||||
import proto from "db://assets/Scripts/proto/proto.pb.js";
|
||||
import { TipsPanel } from "../ui/panels/TipsPanel";
|
||||
import LanguageUtils from "../../Main/Common/LanguageUtils";
|
||||
|
||||
/**
|
||||
* AI聊天服务类
|
||||
@@ -48,12 +49,18 @@ export class ChatAIService {
|
||||
{ config },
|
||||
true
|
||||
);
|
||||
TipsPanel.show(LanguageUtils.getText("chat_error_code_2002"));
|
||||
|
||||
throw new Error("AI服务初始化失败:配置无效");
|
||||
}
|
||||
|
||||
try {
|
||||
this.ai = new GoogleGenAI({ apiKey: config.apiKey });
|
||||
this.ai = new GoogleGenAI({
|
||||
apiKey: config.apiKey,
|
||||
httpOptions: { timeout: ApiConfig.Instance.getTimeout() },
|
||||
});
|
||||
} catch (error) {
|
||||
TipsPanel.show(LanguageUtils.getText("chat_error_code_2001"));
|
||||
ErrorHandler.Instance.handleError(
|
||||
error as Error,
|
||||
ErrorType.API_ERROR,
|
||||
@@ -102,6 +109,23 @@ export class ChatAIService {
|
||||
category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE,
|
||||
},
|
||||
{
|
||||
category: HarmCategory.HARM_CATEGORY_CIVIC_INTEGRITY,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE,
|
||||
},
|
||||
{
|
||||
category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE,
|
||||
},
|
||||
{
|
||||
category: HarmCategory.HARM_CATEGORY_HARASSMENT,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE,
|
||||
},
|
||||
|
||||
{
|
||||
category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE,
|
||||
},
|
||||
],
|
||||
},
|
||||
history: savedHistory,
|
||||
@@ -120,6 +144,23 @@ export class ChatAIService {
|
||||
category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE,
|
||||
},
|
||||
{
|
||||
category: HarmCategory.HARM_CATEGORY_CIVIC_INTEGRITY,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE,
|
||||
},
|
||||
{
|
||||
category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE,
|
||||
},
|
||||
{
|
||||
category: HarmCategory.HARM_CATEGORY_HARASSMENT,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE,
|
||||
},
|
||||
|
||||
{
|
||||
category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
|
||||
threshold: HarmBlockThreshold.BLOCK_NONE,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -245,6 +286,7 @@ export class ChatAIService {
|
||||
|
||||
return response.text;
|
||||
} else {
|
||||
TipsPanel.show(response.promptFeedback.blockReason);
|
||||
const warningMsg = `AI返回了空响应 (角色ID: ${roleId})`;
|
||||
ErrorHandler.Instance.handleError(
|
||||
new Error(warningMsg),
|
||||
@@ -257,7 +299,7 @@ export class ChatAIService {
|
||||
} catch (error) {
|
||||
ErrorHandler.Instance.handleApiError(error, "sendMessage", {
|
||||
roleId,
|
||||
message: message.substring(0, 100) + "...",
|
||||
message: message,
|
||||
});
|
||||
TipsPanel.show("api调用失败,请使用vpn并重新启动");
|
||||
return null;
|
||||
|
||||
@@ -7,6 +7,8 @@ import { ChatModel } from "../data/ChatModel";
|
||||
import { ChatHistoryManager } from "../manager/ChatHistoryManager";
|
||||
import Utils from "../../Main/Common/Utils";
|
||||
import { InnerMsgCode } from "../../Main/Config/InnerMsgCode";
|
||||
import { TipsPanel } from "../ui/panels/TipsPanel";
|
||||
import LanguageUtils from "../../Main/Common/LanguageUtils";
|
||||
|
||||
/**
|
||||
* 聊天控制器接口 - 定义Panel和Controller之间的通信协议
|
||||
@@ -188,7 +190,8 @@ export class ChatController {
|
||||
try {
|
||||
const roleId = this.chatModel.getCurrentRoleId();
|
||||
if (!roleId) {
|
||||
throw new Error("Role ID is not available in ChatModel");
|
||||
console.error("Role ID is not available in ChatModel");
|
||||
TipsPanel.show(LanguageUtils.getText("chat_error_code_1004"));
|
||||
}
|
||||
|
||||
// 添加用户消息到模型
|
||||
|
||||
@@ -40,7 +40,10 @@ export class EmotionAIService {
|
||||
const emotionConfig = ApiConfig.Instance.getEmotionAIConfig();
|
||||
|
||||
try {
|
||||
this.emotionAI = new GoogleGenAI({ apiKey: emotionConfig.apiKey });
|
||||
this.emotionAI = new GoogleGenAI({
|
||||
apiKey: emotionConfig.apiKey,
|
||||
httpOptions: { timeout: emotionConfig.timeout },
|
||||
});
|
||||
} catch (error) {
|
||||
ErrorHandler.Instance.handleError(
|
||||
error as Error,
|
||||
@@ -109,7 +112,9 @@ export class EmotionAIService {
|
||||
|
||||
// 分析历史情绪状态
|
||||
emotionalState = await this.analyzeEmotionalState(roleId);
|
||||
|
||||
if (emotionalState == null) {
|
||||
emotionalState = VideoEmotion.calm_down;
|
||||
}
|
||||
console.log(
|
||||
`Initial emotional state for role ${roleId}: ${VideoEmotion[emotionalState]}`
|
||||
);
|
||||
@@ -185,7 +190,7 @@ export class EmotionAIService {
|
||||
"角色ID必须是正整数",
|
||||
roleId
|
||||
);
|
||||
return VideoEmotion.calm_down;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!message || message.trim() === "") {
|
||||
@@ -194,7 +199,7 @@ export class EmotionAIService {
|
||||
"消息内容不能为空",
|
||||
message
|
||||
);
|
||||
return VideoEmotion.calm_down;
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -214,14 +219,14 @@ export class EmotionAIService {
|
||||
{ roleId, message, response },
|
||||
true
|
||||
);
|
||||
return VideoEmotion.calm_down;
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
ErrorHandler.Instance.handleApiError(error, "sendEmotionMessage", {
|
||||
roleId,
|
||||
message: message.substring(0, 100) + "...",
|
||||
});
|
||||
return VideoEmotion.calm_down;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +256,7 @@ export class EmotionAIService {
|
||||
{ roleId },
|
||||
false
|
||||
);
|
||||
return VideoEmotion.calm_down;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,8 +381,11 @@ export class EmotionAIService {
|
||||
);
|
||||
|
||||
// 发送给情绪AI进行分析
|
||||
const newEmotion = await this.sendEmotionMessage(roleId, analysisPrompt);
|
||||
let newEmotion = await this.sendEmotionMessage(roleId, analysisPrompt);
|
||||
|
||||
if (newEmotion == null) {
|
||||
newEmotion = currentEmotion;
|
||||
}
|
||||
// 更新并保存情绪状态
|
||||
this.setCurrentEmotion(roleId, newEmotion);
|
||||
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
import { ChatAIService } from '../core/ChatAIService';
|
||||
|
||||
/**
|
||||
* ChatAI 批量测试运行器 - 纯脚本版本
|
||||
*
|
||||
* 用法:
|
||||
* ```typescript
|
||||
* const testRunner = new ChatAIBatchTestRunner();
|
||||
* testRunner.runBatchTest();
|
||||
* ```
|
||||
*/
|
||||
export class ChatAIBatchTestRunner {
|
||||
|
||||
private isRunning: boolean = false;
|
||||
|
||||
constructor() {
|
||||
console.log("[ChatAIBatchTestRunner] 测试运行器已初始化");
|
||||
}
|
||||
|
||||
/**
|
||||
* 延时工具函数
|
||||
* @param seconds 延时秒数
|
||||
*/
|
||||
private async delay(seconds: number): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, seconds * 1000);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行批量测试
|
||||
*/
|
||||
public async runBatchTest(): Promise<void> {
|
||||
if (this.isRunning) {
|
||||
console.log("[ChatAIBatchTestRunner] 测试已在运行中,请等待完成...");
|
||||
return;
|
||||
}
|
||||
|
||||
this.isRunning = true;
|
||||
console.log("[ChatAIBatchTestRunner] 开始批量测试角色ID 10001-10030");
|
||||
console.log("[ChatAIBatchTestRunner] 每次测试间隔10秒");
|
||||
|
||||
const startTime = Date.now();
|
||||
const successIds: number[] = [];
|
||||
const failureIds: number[] = [];
|
||||
const errorDetails: { [roleId: number]: string } = {};
|
||||
|
||||
// 测试角色ID 10001-10030
|
||||
for (let roleId = 10001; roleId <= 10030; roleId++) {
|
||||
console.log(`[ChatAIBatchTestRunner] 正在测试角色ID: ${roleId}`);
|
||||
|
||||
const testStartTime = Date.now();
|
||||
|
||||
try {
|
||||
const response = await ChatAIService.Instance.sendMessage(roleId, "hello");
|
||||
const testDuration = Date.now() - testStartTime;
|
||||
|
||||
if (response && response.trim() !== "") {
|
||||
successIds.push(roleId);
|
||||
console.log(`[ChatAIBatchTestRunner] ✅ 角色 ${roleId} 测试成功 (${testDuration}ms)`);
|
||||
console.log(`[ChatAIBatchTestRunner] 响应预览: ${response.substring(0, 50)}...`);
|
||||
} else {
|
||||
failureIds.push(roleId);
|
||||
errorDetails[roleId] = "返回空响应";
|
||||
console.log(`[ChatAIBatchTestRunner] ❌ 角色 ${roleId} 返回空响应 (${testDuration}ms)`);
|
||||
}
|
||||
} catch (error) {
|
||||
const testDuration = Date.now() - testStartTime;
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
|
||||
failureIds.push(roleId);
|
||||
errorDetails[roleId] = errorMessage;
|
||||
console.log(`[ChatAIBatchTestRunner] ❌ 角色 ${roleId} 测试失败 (${testDuration}ms): ${errorMessage}`);
|
||||
}
|
||||
|
||||
// 等待10秒(最后一个不需要等待)
|
||||
if (roleId < 10030) {
|
||||
console.log(`[ChatAIBatchTestRunner] 等待10秒后继续下一个测试...`);
|
||||
await this.delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
|
||||
// 输出最终报告
|
||||
this.printFinalReport(successIds, failureIds, errorDetails, totalDuration);
|
||||
|
||||
this.isRunning = false;
|
||||
console.log("[ChatAIBatchTestRunner] 批量测试完成!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出最终测试报告
|
||||
*/
|
||||
private printFinalReport(
|
||||
successIds: number[],
|
||||
failureIds: number[],
|
||||
errorDetails: { [roleId: number]: string },
|
||||
totalDuration: number
|
||||
): void {
|
||||
const totalTests = 30;
|
||||
const successCount = successIds.length;
|
||||
const failureCount = failureIds.length;
|
||||
const successRate = ((successCount / totalTests) * 100).toFixed(2);
|
||||
|
||||
console.log("\n" + "=".repeat(60));
|
||||
console.log(" ChatAI 批量测试报告");
|
||||
console.log("=".repeat(60));
|
||||
console.log(`测试时间: ${new Date().toLocaleString()}`);
|
||||
console.log(`总测试数: ${totalTests}`);
|
||||
console.log(`成功数量: ${successCount}`);
|
||||
console.log(`失败数量: ${failureCount}`);
|
||||
console.log(`成功率: ${successRate}%`);
|
||||
console.log(`总耗时: ${(totalDuration / 1000).toFixed(2)}秒`);
|
||||
console.log(`平均耗时: ${(totalDuration / totalTests / 1000).toFixed(2)}秒/测试`);
|
||||
|
||||
console.log("\n" + "-".repeat(30) + " 成功的角色ID " + "-".repeat(30));
|
||||
if (successIds.length > 0) {
|
||||
const successList = this.formatIdList(successIds);
|
||||
console.log(successList);
|
||||
} else {
|
||||
console.log("无成功案例");
|
||||
}
|
||||
|
||||
console.log("\n" + "-".repeat(30) + " 失败的角色ID " + "-".repeat(30));
|
||||
if (failureIds.length > 0) {
|
||||
const failureList = this.formatIdList(failureIds);
|
||||
console.log(failureList);
|
||||
|
||||
console.log("\n" + "-".repeat(25) + " 失败详情 " + "-".repeat(25));
|
||||
failureIds.forEach(roleId => {
|
||||
console.log(`角色 ${roleId}: ${errorDetails[roleId]}`);
|
||||
});
|
||||
} else {
|
||||
console.log("无失败案例");
|
||||
}
|
||||
|
||||
console.log("\n" + "=".repeat(60));
|
||||
|
||||
// 输出简洁版结果供复制使用
|
||||
console.log("\n简洁结果:");
|
||||
console.log(`成功(${successCount}): ${successIds.join(',')}`);
|
||||
console.log(`失败(${failureCount}): ${failureIds.join(',')}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化ID列表为易读格式
|
||||
*/
|
||||
private formatIdList(ids: number[]): string {
|
||||
if (ids.length === 0) return "无";
|
||||
|
||||
const sortedIds = ids.sort((a, b) => a - b);
|
||||
const groups: string[] = [];
|
||||
let start = sortedIds[0];
|
||||
let end = sortedIds[0];
|
||||
|
||||
for (let i = 1; i < sortedIds.length; i++) {
|
||||
if (sortedIds[i] === end + 1) {
|
||||
end = sortedIds[i];
|
||||
} else {
|
||||
if (start === end) {
|
||||
groups.push(`${start}`);
|
||||
} else if (end === start + 1) {
|
||||
groups.push(`${start},${end}`);
|
||||
} else {
|
||||
groups.push(`${start}-${end}`);
|
||||
}
|
||||
start = end = sortedIds[i];
|
||||
}
|
||||
}
|
||||
|
||||
// 添加最后一组
|
||||
if (start === end) {
|
||||
groups.push(`${start}`);
|
||||
} else if (end === start + 1) {
|
||||
groups.push(`${start},${end}`);
|
||||
} else {
|
||||
groups.push(`${start}-${end}`);
|
||||
}
|
||||
|
||||
return groups.join(', ');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前运行状态
|
||||
*/
|
||||
public isTestRunning(): boolean {
|
||||
return this.isRunning;
|
||||
}
|
||||
}
|
||||
|
||||
// 全局实例,可以直接调用
|
||||
export const chatAIBatchTester = new ChatAIBatchTestRunner();
|
||||
|
||||
// 便捷的全局函数
|
||||
export async function runChatAIBatchTest(): Promise<void> {
|
||||
await chatAIBatchTester.runBatchTest();
|
||||
}
|
||||
|
||||
// 使用示例:
|
||||
// import { runChatAIBatchTest } from 'path/to/ChatAIBatchTestRunner';
|
||||
// runChatAIBatchTest();
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "76e29352-9c31-48f1-ac08-8646aa63a425",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
import { _decorator, Component, Node, log, Button, Label } from 'cc';
|
||||
import { ChatAIService } from '../core/ChatAIService';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
interface TestResult {
|
||||
roleId: number;
|
||||
success: boolean;
|
||||
response?: string;
|
||||
error?: string;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
interface TestReport {
|
||||
totalTests: number;
|
||||
successCount: number;
|
||||
failureCount: number;
|
||||
successIds: number[];
|
||||
failureIds: number[];
|
||||
results: TestResult[];
|
||||
totalDuration: number;
|
||||
}
|
||||
|
||||
@ccclass('ChatAIServiceBatchTest')
|
||||
export class ChatAIServiceBatchTest extends Component {
|
||||
|
||||
@property(Button)
|
||||
startTestButton: Button = null;
|
||||
|
||||
@property(Label)
|
||||
statusLabel: Label = null;
|
||||
|
||||
@property(Label)
|
||||
resultLabel: Label = null;
|
||||
|
||||
private isTestRunning: boolean = false;
|
||||
private testReport: TestReport = null;
|
||||
|
||||
onLoad() {
|
||||
if (this.startTestButton) {
|
||||
this.startTestButton.node.on(Button.EventType.CLICK, this.startBatchTest, this);
|
||||
}
|
||||
|
||||
this.updateStatus("点击开始按钮进行批量测试");
|
||||
}
|
||||
|
||||
/**
|
||||
* 延时工具函数
|
||||
* @param seconds 延时秒数
|
||||
*/
|
||||
private async delay(seconds: number): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, seconds * 1000);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态显示
|
||||
*/
|
||||
private updateStatus(message: string): void {
|
||||
if (this.statusLabel) {
|
||||
this.statusLabel.string = message;
|
||||
}
|
||||
log(`[ChatAIBatchTest] ${message}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新结果显示
|
||||
*/
|
||||
private updateResult(report: TestReport): void {
|
||||
if (!this.resultLabel) return;
|
||||
|
||||
const resultText = `测试完成!
|
||||
总测试数: ${report.totalTests}
|
||||
成功数: ${report.successCount}
|
||||
失败数: ${report.failureCount}
|
||||
总耗时: ${(report.totalDuration / 1000).toFixed(2)}s
|
||||
|
||||
成功的ID: ${report.successIds.join(', ')}
|
||||
|
||||
失败的ID: ${report.failureIds.join(', ')}`;
|
||||
|
||||
this.resultLabel.string = resultText;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试单个角色ID
|
||||
*/
|
||||
private async testSingleRole(roleId: number): Promise<TestResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
this.updateStatus(`正在测试角色ID: ${roleId}`);
|
||||
|
||||
const response = await ChatAIService.Instance.sendMessage(roleId, "hello");
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
if (response && response.trim() !== "") {
|
||||
log(`[ChatAIBatchTest] 角色 ${roleId} 测试成功: ${response.substring(0, 50)}...`);
|
||||
return {
|
||||
roleId,
|
||||
success: true,
|
||||
response: response.substring(0, 100), // 只记录前100字符
|
||||
duration
|
||||
};
|
||||
} else {
|
||||
log(`[ChatAIBatchTest] 角色 ${roleId} 返回空响应`);
|
||||
return {
|
||||
roleId,
|
||||
success: false,
|
||||
error: "返回空响应",
|
||||
duration
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
log(`[ChatAIBatchTest] 角色 ${roleId} 测试失败: ${errorMessage}`);
|
||||
|
||||
return {
|
||||
roleId,
|
||||
success: false,
|
||||
error: errorMessage,
|
||||
duration
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始批量测试
|
||||
*/
|
||||
public async startBatchTest(): Promise<void> {
|
||||
if (this.isTestRunning) {
|
||||
this.updateStatus("测试正在进行中,请等待...");
|
||||
return;
|
||||
}
|
||||
|
||||
this.isTestRunning = true;
|
||||
|
||||
if (this.startTestButton) {
|
||||
this.startTestButton.interactable = false;
|
||||
}
|
||||
|
||||
if (this.resultLabel) {
|
||||
this.resultLabel.string = "";
|
||||
}
|
||||
|
||||
const startTime = Date.now();
|
||||
const results: TestResult[] = [];
|
||||
const successIds: number[] = [];
|
||||
const failureIds: number[] = [];
|
||||
|
||||
log("[ChatAIBatchTest] 开始批量测试角色ID 10001-10030");
|
||||
this.updateStatus("开始批量测试...");
|
||||
|
||||
// 测试角色ID 10001-10030
|
||||
for (let roleId = 10001; roleId <= 10030; roleId++) {
|
||||
try {
|
||||
// 测试单个角色
|
||||
const result = await this.testSingleRole(roleId);
|
||||
results.push(result);
|
||||
|
||||
if (result.success) {
|
||||
successIds.push(roleId);
|
||||
} else {
|
||||
failureIds.push(roleId);
|
||||
}
|
||||
|
||||
// 等待10秒(最后一个不需要等待)
|
||||
if (roleId < 10030) {
|
||||
this.updateStatus(`角色 ${roleId} 测试完成,等待10秒...`);
|
||||
await this.delay(10);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
log(`[ChatAIBatchTest] 测试角色 ${roleId} 时发生意外错误: ${error}`);
|
||||
results.push({
|
||||
roleId,
|
||||
success: false,
|
||||
error: `意外错误: ${error}`,
|
||||
duration: 0
|
||||
});
|
||||
failureIds.push(roleId);
|
||||
}
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
|
||||
// 生成测试报告
|
||||
this.testReport = {
|
||||
totalTests: 30,
|
||||
successCount: successIds.length,
|
||||
failureCount: failureIds.length,
|
||||
successIds,
|
||||
failureIds,
|
||||
results,
|
||||
totalDuration
|
||||
};
|
||||
|
||||
// 输出详细报告到控制台
|
||||
this.logDetailedReport(this.testReport);
|
||||
|
||||
// 更新UI显示
|
||||
this.updateResult(this.testReport);
|
||||
this.updateStatus("批量测试完成!");
|
||||
|
||||
if (this.startTestButton) {
|
||||
this.startTestButton.interactable = true;
|
||||
}
|
||||
|
||||
this.isTestRunning = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出详细测试报告到控制台
|
||||
*/
|
||||
private logDetailedReport(report: TestReport): void {
|
||||
log("========== ChatAI 批量测试报告 ==========");
|
||||
log(`测试时间: ${new Date().toLocaleString()}`);
|
||||
log(`总测试数: ${report.totalTests}`);
|
||||
log(`成功数: ${report.successCount}`);
|
||||
log(`失败数: ${report.failureCount}`);
|
||||
log(`成功率: ${((report.successCount / report.totalTests) * 100).toFixed(2)}%`);
|
||||
log(`总耗时: ${(report.totalDuration / 1000).toFixed(2)}秒`);
|
||||
log(`平均耗时: ${(report.totalDuration / report.totalTests / 1000).toFixed(2)}秒/测试`);
|
||||
|
||||
log("\n===== 成功的角色ID =====");
|
||||
if (report.successIds.length > 0) {
|
||||
log(report.successIds.join(', '));
|
||||
} else {
|
||||
log("无");
|
||||
}
|
||||
|
||||
log("\n===== 失败的角色ID =====");
|
||||
if (report.failureIds.length > 0) {
|
||||
log(report.failureIds.join(', '));
|
||||
|
||||
log("\n===== 失败详情 =====");
|
||||
report.results
|
||||
.filter(r => !r.success)
|
||||
.forEach(result => {
|
||||
log(`角色 ${result.roleId}: ${result.error}`);
|
||||
});
|
||||
} else {
|
||||
log("无");
|
||||
}
|
||||
|
||||
log("\n===== 详细测试结果 =====");
|
||||
report.results.forEach(result => {
|
||||
const status = result.success ? "成功" : "失败";
|
||||
const duration = (result.duration / 1000).toFixed(2);
|
||||
const extra = result.success
|
||||
? `响应: ${result.response?.substring(0, 30)}...`
|
||||
: `错误: ${result.error}`;
|
||||
log(`角色 ${result.roleId}: ${status} (${duration}s) - ${extra}`);
|
||||
});
|
||||
|
||||
log("========================================");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取测试报告(供外部调用)
|
||||
*/
|
||||
public getTestReport(): TestReport {
|
||||
return this.testReport;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置测试状态
|
||||
*/
|
||||
public resetTest(): void {
|
||||
this.isTestRunning = false;
|
||||
this.testReport = null;
|
||||
|
||||
if (this.statusLabel) {
|
||||
this.statusLabel.string = "点击开始按钮进行批量测试";
|
||||
}
|
||||
|
||||
if (this.resultLabel) {
|
||||
this.resultLabel.string = "";
|
||||
}
|
||||
|
||||
if (this.startTestButton) {
|
||||
this.startTestButton.interactable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "a95a7fa5-11a5-47f0-9cbe-6bd704cbbb74",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
# ChatAI 批量测试工具
|
||||
|
||||
本工具用于批量测试 ChatAIService 的 sendMessage 功能,测试角色ID 10001-10030 的可用性。
|
||||
|
||||
## 文件说明
|
||||
|
||||
### 1. ChatAIServiceBatchTest.ts
|
||||
- **类型**: Cocos Creator 组件
|
||||
- **用途**: 带UI界面的测试工具
|
||||
- **特点**: 需要挂载到节点上,有可视化界面
|
||||
|
||||
### 2. ChatAIBatchTestRunner.ts
|
||||
- **类型**: 纯TypeScript脚本
|
||||
- **用途**: 无UI的批量测试工具
|
||||
- **特点**: 可以直接在代码中调用
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 方法一:使用UI组件版本
|
||||
|
||||
1. 在Cocos Creator中创建一个测试场景
|
||||
2. 创建一个节点并挂载 `ChatAIServiceBatchTest` 组件
|
||||
3. 配置UI元素:
|
||||
- `startTestButton`: 开始测试按钮
|
||||
- `statusLabel`: 状态显示标签
|
||||
- `resultLabel`: 结果显示标签
|
||||
4. 运行场景,点击按钮开始测试
|
||||
|
||||
### 方法二:使用纯脚本版本(推荐)
|
||||
|
||||
在任何TypeScript文件中导入并调用:
|
||||
|
||||
```typescript
|
||||
import { runChatAIBatchTest } from 'db://assets/Scripts/chat18x/test/ChatAIBatchTestRunner';
|
||||
|
||||
// 直接运行测试
|
||||
runChatAIBatchTest();
|
||||
```
|
||||
|
||||
或者使用类实例:
|
||||
|
||||
```typescript
|
||||
import { ChatAIBatchTestRunner } from 'db://assets/Scripts/chat18x/test/ChatAIBatchTestRunner';
|
||||
|
||||
const testRunner = new ChatAIBatchTestRunner();
|
||||
await testRunner.runBatchTest();
|
||||
```
|
||||
|
||||
## 测试流程
|
||||
|
||||
1. 依次测试角色ID 10001 到 10030
|
||||
2. 对每个ID发送消息 "hello"
|
||||
3. 每次调用后等待10秒(最后一个测试不等待)
|
||||
4. 记录成功和失败的角色ID
|
||||
5. 输出详细的测试报告
|
||||
|
||||
## 测试报告内容
|
||||
|
||||
- 总测试数量
|
||||
- 成功/失败数量和比例
|
||||
- 成功的角色ID列表
|
||||
- 失败的角色ID列表及错误原因
|
||||
- 每个测试的耗时统计
|
||||
- 总耗时和平均耗时
|
||||
|
||||
## 示例输出
|
||||
|
||||
```
|
||||
==============================================================
|
||||
ChatAI 批量测试报告
|
||||
==============================================================
|
||||
测试时间: 2024/3/15 14:30:25
|
||||
总测试数: 30
|
||||
成功数量: 25
|
||||
失败数量: 5
|
||||
成功率: 83.33%
|
||||
总耗时: 315.68秒
|
||||
平均耗时: 10.52秒/测试
|
||||
|
||||
------------------------------ 成功的角色ID ------------------------------
|
||||
10001-10015, 10017-10025, 10028
|
||||
|
||||
------------------------------ 失败的角色ID ------------------------------
|
||||
10016, 10026, 10027, 10029, 10030
|
||||
|
||||
------------------------- 失败详情 -------------------------
|
||||
角色 10016: API调用超时
|
||||
角色 10026: 返回空响应
|
||||
角色 10027: 网络连接失败
|
||||
角色 10029: API密钥无效
|
||||
角色 10030: 角色配置不存在
|
||||
==============================================================
|
||||
|
||||
简洁结果:
|
||||
成功(25): 10001,10002,10003,10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,10014,10015,10017,10018,10019,10020,10021,10022,10023,10024,10025,10028
|
||||
失败(5): 10016,10026,10027,10029,10030
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 确保 ChatAIService 已正确初始化
|
||||
2. 测试过程中不要关闭应用,总耗时约5-6分钟
|
||||
3. 测试结果会输出到控制台,注意查看
|
||||
4. 建议在开发环境下运行测试
|
||||
5. 如需中断测试,重启应用即可
|
||||
|
||||
## 技术细节
|
||||
|
||||
- 使用 Promise 和 async/await 处理异步操作
|
||||
- 通过 setTimeout 实现精确的10秒延时
|
||||
- 自动错误捕获和分类
|
||||
- 智能的ID列表格式化显示
|
||||
- 详细的执行时间统计
|
||||
|
||||
## 故障排除
|
||||
|
||||
如果测试无法启动:
|
||||
1. 检查 ChatAIService 是否正确导入
|
||||
2. 确认 AI API 配置是否有效
|
||||
3. 查看控制台错误信息
|
||||
4. 确保网络连接正常
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "1.0.1",
|
||||
"importer": "text",
|
||||
"imported": true,
|
||||
"uuid": "0bad818f-088c-4639-905a-324516bbdafb",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import { DataId, DataManager } from "../../data/DataManager";
|
||||
import { NavigationManager } from "../../manager/NavigationManager";
|
||||
import ResManager from "../../../Main/Manager/ResManager";
|
||||
import { EnvData } from "../../data/EnvData";
|
||||
import Utils from "../../../Main/Common/Utils";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass("DialogBubble")
|
||||
@@ -54,6 +55,24 @@ export class DialogBubble extends Component {
|
||||
|
||||
this.content.overflow = Overflow.NONE;
|
||||
|
||||
//设置头像
|
||||
if (isPlayer) {
|
||||
//获取玩家头像,等接入luffa
|
||||
} else {
|
||||
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||
const path = girlData.getGrilAvatar(
|
||||
NavigationManager.Instance.getSelectedCategoryId().toString(),
|
||||
NavigationManager.Instance.getSelectedGirlId()
|
||||
);
|
||||
|
||||
// 加载远程资源
|
||||
const envData = DataManager.I.getDataById<EnvData>(DataId.Env);
|
||||
let newPath = envData.cdn + "/" + "Girls/" + path + ".png";
|
||||
ResManager.I.changeRemoteSpriteFrame(this.avatar, newPath, () => {
|
||||
this.scaleToFillItem(this.avatar, new Size(90, 90));
|
||||
});
|
||||
}
|
||||
|
||||
// 如果是加载状态,使用固定的"..."
|
||||
if (isLoading) {
|
||||
this.content.string = "...";
|
||||
@@ -121,23 +140,46 @@ export class DialogBubble extends Component {
|
||||
// 返回预估的背景高度(用于同步计算)
|
||||
const estimatedHeight = Math.max(lines.length * 35 + 20, 60); // 最小高度60
|
||||
|
||||
//设置头像
|
||||
if (isPlayer) {
|
||||
//获取玩家头像,等接入luffa
|
||||
} else {
|
||||
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||
const path = girlData.getGrilAvatar(
|
||||
NavigationManager.Instance.getSelectedCategoryId().toString(),
|
||||
NavigationManager.Instance.getSelectedGirlId()
|
||||
);
|
||||
return estimatedHeight;
|
||||
}
|
||||
|
||||
// 加载远程资源
|
||||
const envData = DataManager.I.getDataById<EnvData>(DataId.Env);
|
||||
let newPath = envData.cdn + "/" + "Girls/" + path + ".png";
|
||||
ResManager.I.changeRemoteSpriteFrame(this.avatar, newPath, () => {});
|
||||
scaleToFillItem(img: Sprite, size: Size) {
|
||||
if (!img || !img.spriteFrame) return;
|
||||
|
||||
// 延迟一帧确保UI布局完成
|
||||
this.doScaleToFill(img, size);
|
||||
}
|
||||
|
||||
doScaleToFill(img: Sprite, size: Size) {
|
||||
if (!img || !img.spriteFrame) return;
|
||||
|
||||
const itemSize = size;
|
||||
const imageSize = img.spriteFrame.originalSize;
|
||||
|
||||
if (
|
||||
itemSize.width === 0 ||
|
||||
itemSize.height === 0 ||
|
||||
imageSize.width === 0 ||
|
||||
imageSize.height === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
return estimatedHeight;
|
||||
const scaleX = itemSize.width / imageSize.width;
|
||||
const scaleY = itemSize.height / imageSize.height;
|
||||
const scale = Math.max(scaleX, scaleY);
|
||||
|
||||
// 设置Sprite的sizeMode为CUSTOM,允许自定义大小
|
||||
img.sizeMode = Sprite.SizeMode.CUSTOM;
|
||||
|
||||
// 获取图片节点的UITransform并设置大小
|
||||
const imgTransform = img.node.getComponent(UITransform);
|
||||
if (imgTransform) {
|
||||
imgTransform.setContentSize(
|
||||
imageSize.width * scale,
|
||||
imageSize.height * scale
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private stopLoadingAnimation() {
|
||||
|
||||
@@ -73,7 +73,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
||||
categoryId: string;
|
||||
id: number;
|
||||
private _nodeTab: any = {};
|
||||
|
||||
private waitingAI: Node;
|
||||
nameKey: string;
|
||||
private currentEmotion: VideoEmotion | null = null;
|
||||
|
||||
@@ -87,6 +87,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
||||
onLoadCT() {
|
||||
Utils.parseNode(this.node, this._nodeTab);
|
||||
|
||||
this.waitingAI = this._nodeTab.waitingAI;
|
||||
// 获取 videoArea 的尺寸和位置
|
||||
this.targetSize = this.videoArea.contentSize;
|
||||
this.videoAreaPos = new Vec3(540, 1170, 0);
|
||||
@@ -150,7 +151,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
||||
async refresh() {
|
||||
const newRoleId = NavigationManager.Instance.getSelectedGirlId();
|
||||
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||
|
||||
this.waitingAI.active = false;
|
||||
// 检查是否是切换角色
|
||||
const isRoleSwitch = this.id && this.id !== newRoleId;
|
||||
|
||||
@@ -399,18 +400,27 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
isWaiting: boolean = false;
|
||||
public async OnClickSend() {
|
||||
const str = this.editBox.string;
|
||||
if (!str || str == "") {
|
||||
TipsPanel.show("请输入内容");
|
||||
TipsPanel.show(LanguageUtils.getText("chat_error_code_1002"));
|
||||
return;
|
||||
}
|
||||
if (this.isWaiting) {
|
||||
TipsPanel.show(LanguageUtils.getText("chat_error_code_1003"));
|
||||
}
|
||||
|
||||
// 通过ChatController发送消息
|
||||
this.isWaiting = true;
|
||||
this.waitingAI.active = true;
|
||||
const succeed = await this.chatController.sendMessage(str);
|
||||
if (succeed)
|
||||
if (succeed) {
|
||||
// 清空输入框
|
||||
this.editBox.string = "";
|
||||
}
|
||||
this.isWaiting = false;
|
||||
this.waitingAI.active = false;
|
||||
}
|
||||
|
||||
// === IChatPanelCallback 接口实现 ===
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,624 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.AnimationClip",
|
||||
"_name": "chat_waiting",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {
|
||||
"embeddedPlayerGroups": []
|
||||
},
|
||||
"_native": "",
|
||||
"sample": 60,
|
||||
"speed": 1,
|
||||
"wrapMode": 2,
|
||||
"enableTrsBlending": false,
|
||||
"_duration": 0.75,
|
||||
"_hash": 500763545,
|
||||
"_tracks": [
|
||||
{
|
||||
"__id__": 1
|
||||
},
|
||||
{
|
||||
"__id__": 12
|
||||
},
|
||||
{
|
||||
"__id__": 23
|
||||
}
|
||||
],
|
||||
"_exoticAnimation": null,
|
||||
"_events": [],
|
||||
"_embeddedPlayers": [],
|
||||
"_additiveSettings": {
|
||||
"__id__": 34
|
||||
},
|
||||
"_auxiliaryCurveEntries": []
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.VectorTrack",
|
||||
"_binding": {
|
||||
"__type__": "cc.animation.TrackBinding",
|
||||
"path": {
|
||||
"__id__": 2
|
||||
},
|
||||
"proxy": null
|
||||
},
|
||||
"_channels": [
|
||||
{
|
||||
"__id__": 4
|
||||
},
|
||||
{
|
||||
"__id__": 6
|
||||
},
|
||||
{
|
||||
"__id__": 8
|
||||
},
|
||||
{
|
||||
"__id__": 10
|
||||
}
|
||||
],
|
||||
"_nComponents": 3
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.TrackPath",
|
||||
"_paths": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
"position"
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.HierarchyPath",
|
||||
"path": "dot"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [
|
||||
0,
|
||||
0.28333333134651184,
|
||||
0.550000011920929
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": -262.56298828125,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": -262.56298828125,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": -262.56298828125,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [
|
||||
0,
|
||||
0.28333333134651184,
|
||||
0.550000011920929
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 2,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 0,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 2,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 22.399999618530273,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 2,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 0,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [
|
||||
0,
|
||||
0.28333333134651184
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 0,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 0,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [],
|
||||
"_values": [],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.VectorTrack",
|
||||
"_binding": {
|
||||
"__type__": "cc.animation.TrackBinding",
|
||||
"path": {
|
||||
"__id__": 13
|
||||
},
|
||||
"proxy": null
|
||||
},
|
||||
"_channels": [
|
||||
{
|
||||
"__id__": 15
|
||||
},
|
||||
{
|
||||
"__id__": 17
|
||||
},
|
||||
{
|
||||
"__id__": 19
|
||||
},
|
||||
{
|
||||
"__id__": 21
|
||||
}
|
||||
],
|
||||
"_nComponents": 3
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.TrackPath",
|
||||
"_paths": [
|
||||
{
|
||||
"__id__": 14
|
||||
},
|
||||
"position"
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.HierarchyPath",
|
||||
"path": "dot-001"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [
|
||||
0.0833333358168602,
|
||||
0.36666667461395264,
|
||||
0.6333333253860474
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": -232.46299743652344,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": -232.56300354003906,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": -232.56300354003906,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [
|
||||
0.0833333358168602,
|
||||
0.36666667461395264,
|
||||
0.6333333253860474
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 2,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 0,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 2,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 22.399999618530273,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 2,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 0,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [],
|
||||
"_values": [],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [],
|
||||
"_values": [],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.VectorTrack",
|
||||
"_binding": {
|
||||
"__type__": "cc.animation.TrackBinding",
|
||||
"path": {
|
||||
"__id__": 24
|
||||
},
|
||||
"proxy": null
|
||||
},
|
||||
"_channels": [
|
||||
{
|
||||
"__id__": 26
|
||||
},
|
||||
{
|
||||
"__id__": 28
|
||||
},
|
||||
{
|
||||
"__id__": 30
|
||||
},
|
||||
{
|
||||
"__id__": 32
|
||||
}
|
||||
],
|
||||
"_nComponents": 3
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.TrackPath",
|
||||
"_paths": [
|
||||
{
|
||||
"__id__": 25
|
||||
},
|
||||
"position"
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.HierarchyPath",
|
||||
"path": "dot-002"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 27
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [
|
||||
0.20000000298023224,
|
||||
0.46666666865348816,
|
||||
0.75
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": -202.56300354003906,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": -202.56300354003906,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": -202.56300354003906,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 29
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [
|
||||
0.20000000298023224,
|
||||
0.46666666865348816,
|
||||
0.75
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 2,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 0,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 2,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 22.399999618530273,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 2,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 0,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 1,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 1,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": {
|
||||
"tangentMode": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 31
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [],
|
||||
"_values": [],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 33
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [],
|
||||
"_values": [],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.AnimationClipAdditiveSettings",
|
||||
"enabled": false,
|
||||
"refClip": null
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "2.0.3",
|
||||
"importer": "animation-clip",
|
||||
"imported": true,
|
||||
"uuid": "aa04af0a-fa02-48bb-8423-66b7aac1f1b4",
|
||||
"files": [
|
||||
".cconb"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"name": "chat_waiting"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user